Grep 多个文件每次都重定向到不同的文件名

Grep 多个文件每次都重定向到不同的文件名

我有一个充满 .tsv 文件的目录,我想对每个文件运行 grep 命令以提取一组特定的文本行,然后将其保存到具有相似文件名的关联文本文件中。例如,如果我只 grep 一个文件,我的 grep 命令如下所示:

grep -h 8-K 2008-QTR1.tsv > 2008Q1.txt

但我有一个 tsv 文件列表,如下所示:

2008-QTR1.tsv
2008-QTR2.tsv
2008-QTR3.tsv
2008-QTR4.tsv
2009-QTR1.tsv
2009-QTR2.tsv
2009-QTR3.tsv
...

在 grep 后,它们需要存储为:

2008Q1.txt
2008Q2.txt
2008Q3.txt
2008Q4.txt
2009Q1.txt
2009Q2.txt
2009Q3.txt

有什么想法吗?

答案1

在ksh93/bash/zsh中,通过简单的for循环和参数扩展:

for f in *-QTR*.tsv
do 
  grep 8-K < "$f" > "${f:0:4}"Q"${f:8:1}".txt
done

grep一次运行一个文件(其中文件列表是根据通配符模式生成的,该模式要求文件名中存在“-QTR”以及文件名结尾的“.tsv”),将输出重定向到基于以下内容精心构建的文件名:

  • 文件名的前四个字符——年份
  • 这封信Q
  • 文件名的第 9 个字符——季度

答案2

强制性的 POSIXsh变体:

#! /bin/sh -
ret=0
for file in [[:digit:]][[:digit:]][[:digit:]][[:digit:]]-QTR[1234].tsv; do
  base=${file%.tsv}
  grep 8-K < "$file" > "${base%%-*}Q${base##*-QTR}".txt || ret=$?
done
exit "$ret"

答案3

另外一个选择

for f in  200{8..9}-QTR{1..4}.tsv; do
    grep "pattern" $f > $(sed "s/[-RTtsv]*//g" <<< $f)txt;
done

演练:设置一个扩展来创建文件名列表

200{8..9}-QTR{1..4}.tsv

扩展到

2008-QTR1.tsv 2008-QTR2.tsv 2008-QTR3.tsv 2008-QTR4.tsv 2009-QTR1.tsv 2009-QTR2.tsv 2009-QTR3.tsv 2009-QTR4.tsv

迄今为止每年和每个季度要做的事情是

20{08..19}-QTR{1..4}.tsv

遍历列表for..do..done,从文件中提取您要查找的模式

grep "pattern" $f

并重定向到通过删除不需要的字符sed并添加txt后缀形成的新文件名

$(sed "s/[-RTtsv]*//g" <<< $f)txt

或者

$(sed "s/[-RT]*//g" <<< ${f%%.*}.txt)

答案4

如果想避免显式循环,有以下解决方案。也许有人能够改进它。它看起来像这样。

ls -1 *.tsv | xargs -n1 -I'{}' bash -c 'f="{}";grep 8-K $f > ${f//[^0-9Q]/}.txt'
  1. LS仅列出您要处理的文件
  2. 参数逐个处理这些文件中的每一个(-n1
  3. A巴什启动 shell 以便能够处理字符串(参见第 5 点)
  4. 将文件名设置为变量$f
  5. ${f//[^0-9Q]/}删除 .txt 文件名中不需要的所有字符(因此这是特定于您的示例的)

优点: - 简单的一个衬垫

缺点: - 为每个处理的文件启动一个 bash 进程

也许有一个不使用 bash 的类似解决方案,但我不知道(例如, eval 不应该在这种情况下工作)

相关内容