【问题标题】:awk in subprocess call fails for multiple pipes多个管道的子进程调用中的 awk 失败
【发布时间】:2021-04-06 09:52:39
【问题描述】:

我正在尝试执行 awk 命令来处理 python 脚本中的一些文本文件。以下行将打印输入文件的最后 2 列并按第二列排序。此命令有效: subprocess.call(["awk",'{print $NF,$(NF-1) | "sort -k 2 -n" }', file2],stdout=f3).

现在我想从已排序的文件中删除 NF col。我添加了以下行,它在“管道”上给出了语法错误 subprocess.call(["awk",'{print $NF,$(NF-1) | "sort -k 2 -n" | '$NF="";print'}', file2],stdout=f3)

我的语法中缺少什么?

【问题讨论】:

  • 您是否真的愿意让awk 负责启动sort? (如果是这样,您是否有一个常规的 shell 命令以您想要的方式运行,所以我们可以将问题的 Python 特定部分与一般 shell+awk 的问题区分开来?)
  • ...请注意,也可以很容易地让 awk 在内部进行排序,而不是让它启动单独的 sort 可执行文件。
  • 但是,一个人也可以很容易地在 Python 中完成整个过程,而根本不需要 awk sort
  • @tripleee,我不确定这是不是特定链接原件的副本。修改前的工作代码示例在上下文中使用管道,它是一个 awk 构造(尽管是一个启动 shell 的 awk 构造,而且使用它通常是一个非常糟糕的主意)而不是 shell 构造。
  • @CharlesDuffy Ack,很抱歉没有正确阅读。无论如何,我选择的欺骗可能是模糊相关的,尽管这个问题对于规范来说并不是特别好; stackoverflow.com/questions/24306205/…

标签: python awk subprocess


【解决方案1】:

即使没有 Python 参与任何地方,这也不起作用;这是一个 awk 问题,而不是 Python 或 subprocess 问题。

如果你的 shell 代码是:

awk '{print $NF,($NF-1) | "sort -k 2 -n" | $NF=""; print}'

...它仍然会因管道字符上的 awk 语法错误而失败:

awk: syntax error at source line 1
 context is
    {print(NF),$(NF-1) | "sort -k 2 -n" >>>  | <<<  $NF="";print}
awk: illegal statement at source line 1

相比之下,可以通过使用三进程管道使其在 shell 中工作:

awk '{print $NF, $(NF - 1)}' file2 \
  | sort -nk2 \
  | awk '{ $NF=""; print }' >file3

...这在 Python 中也可以正常工作:

p1 = subprocess.Popen(['awk', '{print $NF, $(NF - 1)}', file2],
                      stdout=subprocess.PIPE)
p2 = subprocess.Popen(['sort', '-nk1'],
                      stdin=p1.stdout, stdout=subprocess.PIPE)
p3 = subprocess.Popen(['awk', '{ $NF=""; print }'],
                      stdin=p2.stdout, stdout=open(file3, 'w'))

p1.stdout.close()
p2.stdout.close()
p3.wait()

...虽然这比在原生 Python 中执行所有逻辑要麻烦得多,而且根本不需要 awksort

content = [ line.split()[-2:] for line in open(file1).readlines() ]
content.sort(key=lambda x: x[1])
open(file3, 'w').write('\n'.join([item[0] for item in content]) + '\n')

【讨论】:

  • @Anu,顺便说一句——请参阅附录显示如何在 Python 中完成所有工作而不需要 awk sort
  • 谢谢。 python的漂亮紧凑解决方案。我可能会尝试使用上述解决方案的组合。假设我的 csv 中有 10 个列。我想在我的新 csv 文件中捕获第 1 列 + 最后 2 列,按第 1 列对新 csv 文件进行排序,排序后,删除第 1 列。也许我可以使用 popen 创建一个新的 csv 并使用 python 解决方案。
  • Python 有一个非常棒的 CSV 库。我不知道您的数据最初来自哪里,但总的来说,构建 CSV 是一件好事。
  • 我使用了查尔斯提供的建议。这是我的最终解决方案:subprocess.call(["awk","-F,",'{print $1,$(NF-1),$NF }', file1],stdout=output) content = [ line.split(' ',1) for line in open(os.path.abspath(outfile)).readlines() ]content.sort(key=lambda x:x[0]) 然后写入文件
猜你喜欢
  • 2015-05-04
  • 2017-03-10
  • 2020-05-02
  • 2016-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-13
  • 1970-01-01
相关资源
最近更新 更多