Windows CLI:将列表通过管道传输到 awk 并用外部文件中的文本替换文本并写入 output.txt

Posted

技术标签:

【中文标题】Windows CLI:将列表通过管道传输到 awk 并用外部文件中的文本替换文本并写入 output.txt【英文标题】:Windows CLI: pipe a list to awk and replace text with text from an external file and write output.txt 【发布时间】:2014-10-28 09:10:10 【问题描述】:

我是这个东西的新手,遇到了这个问题,我就是想不通:

在 Windows 命令行 (cmd) 中运行的程序 (eG listfilesonhdd) 列出 hdd 上包含大量信息的文件,然后将其通过管道传输到 awk,因为某些文本(带空格)需要替换为文本(带空格) ) 在外部文本文件中,文件如下所示:

assoc.txt:

"this needs to be replaced" "with that"
"and that is replaced" "by that"
"and so on" "it goes"
"TO REPLACE" "WITH"

第一列中的文本需要替换为第二列中的文本。 awk 必须替换来自其他程序的“流”中的匹配项。

所以我尝试了这个命令行

listfilesonhdd | awk "FNR==NR assoc[$1]=$2; next; FNR<NR for(key in assoc) gsub(key, assoc[key]) printf" assoc.txt > output.txt

还有

listfilesonhdd | awk "NR==FNR  a[$1]=$2; next for(i in a) for(x=1;x<=NF;x++) $x=(i==$x)?a[i]:$x1" assoc.txt > output.txt

以及我在这里找到的其他变体,但它总是给我这个错误,有时 FNR 数字会改变,不管我尝试改变什么:

awk: (FILENAME=- FNR=10) warning: error writing standard output (Invalid argument)

这可能意味着文件丢失了,它必须替换文本,但我还没有文件名,我只有这个管道数据,可以这么说。哦,用gawk也试过了,同样的错误。

我在谷歌上搜索了好几天,但我迷路了,我真的很感激,如果有人可以帮助我找到错误,请提前非常感谢你(对不起我的英语)。

【问题讨论】:

"this needs to be replaced" 不是 awk 的单个字段。它有五个字段:"thisneedstobereplaced。所以你的 awk 脚本没有做你想做的事。此外,至少在这里,awk 不会像那样从文件和标准输入中读取数据(不是没有将 - 列为文件名参数之一)。 【参考方案1】:

printf 需要参数。你可能想要print。您可能也想删除 FNR&lt;NR 条件,因为它没有增加任何价值。此外,Windows 引用是一场噩梦,所以请输入您的 awk 脚本:

FNR==NR assoc[$1]=$2; next
 for(key in assoc) gsub(key, assoc[key]); print 

在一个文件中,比如foo.awk 并执行它

listfilesonhdd | awk -f foo.awk assoc.txt - > output.txt

消除这个问题。

我使用- 表示标准输入,如果这不是 WIndows 中的语法,请适当更改(我是 UNIX 人)。

您需要告诉 awk 如何通过设置 FS 或 FPAT 或其他方式将输入分隔到字段中。

请注意,循环中的gsub(key,assoc[key]) 可以替换部分匹配项(例如,您想将the 更改为a,但发现there 转换为are)并且可以替换已经被替换的文本,因此它是可疑的方法。您可能只想循环输入字段并执行if ($i == key) $i = assoc[key] 或类似操作。

要演示告诉 awk 如何识别字段的问题,请查看在您发布的示例输入文件上运行此操作时默认设置的空格分隔字段之间的区别:

$ awk 'NR==1for (i=1;i<=NF;i++) print NR, i, $i' assoc.txt
1 1 "this
1 2 needs
1 3 to
1 4 be
1 5 replaced"
1 6 "with
1 7 that"

vs 告诉 awk 字段是双引号之间并包含双引号的字符串:

$ awk -v FPAT='"[^"]+"' 'NR==1for (i=1;i<=NF;i++) print NR, i, $i' assoc.txt
1 1 "this needs to be replaced"
1 2 "with that"

vs 非双引号字符串:

$ awk -v FPAT='[^"]+' 'NR==1for (i=1;i<=NF;i++) print NR, i, $i' assoc.txt
1 1 this needs to be replaced
1 2
1 3 with that

最后的那些使用 FPAT,它是一个 GNU awk 扩展。其他 awk 有不同的解决方案,但这是最简单的。

【讨论】:

嗨@Ed,谢谢你的回答。当然是print而不是printf,我复制错了。我删除了 FNR 正如@EtanReiser 和我都提到的,您需要告诉 awk 如何将您的输入分成字段。默认情况下,字段以空格分隔,因此每个单独的单词都是一个字段。看起来您想替换整个句子 - awk 如何判断一个句子何时结束而另一个句子何时开始?句子之间是否有制表符,而句子中没有制表符,还是别的什么?相同的规则是否适用于两个输入流?将listfilesonhold 命令管道的输出示例发布到 awk 中,以及所需的输出。 我更新了我的答案以演示告诉 awk 如何识别字段的问题。

以上是关于Windows CLI:将列表通过管道传输到 awk 并用外部文件中的文本替换文本并写入 output.txt的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 CLI 将 zip 文件上传和部署到 AWS elastic beanstalk?

如何将 find 命令返回的文件列表通过管道传输到 cat 以查看所有文件

我可以将多个 ffmpeg 输出通过管道传输到不同的管道吗?

支持的 libvips CLI 输出到 Windows 标准输出的格式

使用谷歌传输服务将文件从 AWS 传输到 GCP 时出现凭证错误

如何将 Python 的 cmd 类的输入/输出通过管道传输到另一个 Python 进程?