Grep / awk 将多个文件转换为单个输出

Grep / awk 将多个文件转换为单个输出

我有几个包含数据的 txt 文件,我用来grep搜索当前的文本字符串,并用来awk过滤掉我需要的变量。该字符串在文件中重复,因此我当前使用此命令来提取所需的字符串:

grep 'text' *.txt | awk ' NR==1  {print $2 } ' > outputfile

问题是我想循环浏览文件夹中的多个文件,并为每个文件将提取的变量写入单个输出文件中。我知道这个问题之前已经得到了回答,但我对此很陌生,并且在实施时遇到一些困难。

任何反馈将不胜感激!

答案1

我将迭代 bash 中的文件,保留每个文件的文件名,以便您可以将每次迭代的输出重定向到不同的输出文件。

例如这样(未测试):

PREFIX="/tmp/outputs"   # define where to store all the outputs
mkdir -p "${PREFIX}"    # make sure the outputs dir exists

for FILE in *.txt       # get the file names you want to work on
do
  # use ${PREFIX}/${FILE} to redirect output to a 
  # file that's associated with the input
  grep 'text' "${FILE}" | awk ' NR==1 {print $2 } ' > "${PREFIX}/${FILE}"
done

答案2

如果我理解正确的话,您需要对每个.txt文件执行以下操作:

  • 找到包含该模式的第一行text
  • 在此行中,获取第二个以空格分隔的字段并将其写入名称与输入文件相关的文件中。

您没有说明应该如何构造输出文件名。我将使其与输入文件相同,但.out.txt.

您可以使用 shell 循环来完成此操作。

for x in *.txt; do
  grep 'text' -- "$x" | awk '{print $2; exit}' >"${x%.*}.out"
done

awk 完成工作后立即退出比告诉它继续阅读但什么也不做要快一些。另一种可能性是完全跳过 awk 并让 shell 进行行分割(这是否更快或更慢取决于很多因素,我不会冒险预测):

for x in *.txt; do
  grep 'text' -- "$x" | read -r first second rest && printf '%s\n' "$rest" >"${x%.*}.out"
done

另一种方法是在 awk 中完成所有工作。 awk 可以作用于多个文件,并且您可以使用 awk 的重定向来输出。这需要分叉更少的进程。在 Gawk (GNU awk) 中这非常简单:

awk '/text/ {print $2 >substr(FILENAME, 1, length(FILENAME)-4) ".out"; nextfile}' *.txt

在没有 的 awk 实现中nextfile,您需要手动处理到下一个文件的转换,这使得这种方法不太有吸引力(更复杂且效率更低)。

awk '
    FNR==1 {first=1}
   first && /text/ {print $2 >substr(FILENAME, 1, length(FILENAME)-4) ".out"; first=0}' *.txt

相关内容