Shell 如何使用awk命令从多个文件中查找并删除正文中包含某些字符串的文件?

Shell 如何使用awk命令从多个文件中查找并删除正文中包含某些字符串的文件?,shell,awk,Shell,Awk,我在文件目录记录中有多个文件: Record 1.txt 2.txt 3.txt 文件2.txt在第一行的第二列中包含一个字符串abcd。如何打印2.txt中的所有内容? 如何删除文件2.txt 我使用awk打印该文件中的所有内容,但它只打印该行 我使用find命令将文件名存储在file.txt文件夹中,但它给了我一个错误 rm -rf Record mkdir Record cd Record echo f1 touch 1.txt echo author: efg &

我在文件目录
记录中有多个文件

Record
   1.txt
   2.txt
   3.txt
文件
2.txt
在第一行的第二列中包含一个字符串
abcd
。如何打印
2.txt
中的所有内容? 如何删除文件2.txt

我使用
awk
打印该文件中的所有内容,但它只打印该行

我使用
find
命令将文件名存储在
file.txt
文件夹中,但它给了我一个错误

rm -rf Record
mkdir Record
cd Record
echo f1
touch 1.txt
echo author: efg   > 1.txt
echo title: hijk  >> 1.txt
echo pages: 1990  >> 1.txt
echo year: 1890  >> 1.txt
touch 2.txt
echo author: abcd > 2.txt
echo author: lmno >> 2.txt
echo title: pqrs >> 2.txt
echo pages: 354 >> 2.txt
echo year:  1970 >> 2.txt
touch 3.txt
echo author: aklj > 3.txt
echo title: dban  >> 3.txt
echo pages: 876  >> 3.txt
echo year: 1860  >> 3.txt
cd ..
adress=./Record/*.txt
sfind=abcd
  awk ' BEGIN { sfind = ENVIRON["sfind"] }
    FNR == 1 { secondPass = seen[FILENAME]++ }
    secondPass { print FILENAME, $0; next }
    index($2,sfind) {
        ARGV[ARGC] = FILENAME
        ARGC++
        nextfile       
    }
'
$adress
上面对输入文件进行了两次传递-第一次传递用于标识那些包含
sfind
中存储的字符串值的文件,并将其添加回ARGV[]的and中,以便稍后再次处理,第二次传递用于打印第一次传递中标识的那些文件的内容。如果不希望在每个输出行的开头打印输入文件名,只需将
打印文件名$0更改为
打印

以上内容适用于任何数量的文件(0、1、2,无论什么)中的任何数量的匹配,适用于任何文件名,即使它们包含空格、全局字符等,以及
sfind
中的任何字符,包括反斜杠转义和regexp metcharacter,如
*

上面的部分字符串匹配。以下是您的选择:

  • 部分字符串:
    索引($2,sfind)
    (如图所示)
  • 完整字段字符串:
    $2==sfind
  • 部分regexp:
    $2~sfind
  • 完整字段regexp:
    $2~(“^”sfind“$”)
完整的单词匹配变得更加复杂,这取决于您对“单词”的定义,并且可以由特定于实现的构造提供服务,因此除非您需要,否则我将省略它。

使用GNU
grep

cat "$(grep -l abcd  *.txt | head -n 1)"
…或以长期权形式:

cat "$(grep --files-with-matches abcd  *.txt | head -n 1)"

要首先打印文件名,请执行以下操作:

n="$(grep -l abcd  *.txt | head -n 1)"
echo "-------- $n -------- "
cat "$n"

问题中的awk命令包含语法和语义错误。在请求命令帮助时,显示实际命令非常重要。请指定列分隔符。显然,根据您所说的
如何查找文件
,以及您提供的示例,您得到了一些答案(请参阅
cat“$(grep…)
答案)假设您总是在1个文件中找到您要查找的字符串,它永远不会出现在任何文件中,也永远不会出现在2个或更多文件中。如果这是一个正确的假设,你应该更新你的答案,说明这一点。如果这是一个错误的假设,您应该更新您的答案,说明这些情况可能发生,以及您希望如何处理它们。您还得到了一些答案,这些答案是使用regexp而不是字符串匹配,可能是因为尽管您说了“如何查找包含某些字符串的文件”然后,您展示了使用regexp
/…/
而不是字符串
“…”
分隔符的示例。因此,请同时更新您的问题,以澄清您是否正在尝试进行regexp或字符串匹配,以及在您进行匹配时,是否希望进行整个字段、整个“单词”或部分匹配(例如,
是否匹配
那里的
)。如果任何文件中都不存在
cd
,则会从
cat
生成错误消息和故障退出状态,如果
cd
存在多个文件,则只打印一个文件的内容。@EdMorton,OP的标题是“…查找文件…”是的,它当然会,也不会讨论如果没有或多个文件匹配该怎么办。@EdMorton,OTOH,更少……这是我第一个想到的。也解释得很好。当你颠倒逻辑的时候,你可以把它稍微缩短一点
BEGIN{sfind=ENVIRONMENT[“sfind']}seed[FILENAME]+{print FILENAME,$0;next}index($2,sfind){ARGV[ARGC++]=FILENAME;nextfile}
@kvantour谢谢。某人(我不记得大概20年前在comp.unix.shell或comp.lang.awk的usenet上是谁,在哪里,什么时候,但我确实记得被说服了)曾经通过引用
ARGV[ARGC++]=foo
不能保证所有AWK中的
ARGC++
都发生在作业之后,而不是之前,因此我一直在犹豫是否使用它。因为我不确定,但在打高尔夫球时不太关心进一步的调查,所以我使用它,否则我不会。我尝试使用此逻辑,但它会打印文件中的所有文件内容记录目录。@maik_eshe除了每一行的第一行之外,其他都是,对吗?是的,我看到了这个bug。这就是为什么在你的问题中提供可测试的样本输入/输出很重要的原因之一(我应该知道在没有它的情况下回答问题会更好),所以我们有一些东西可以测试潜在的解决方案。我用我认为应该解决的东西更新了我的答案,但是,当然,它还没有经过测试,因为您还没有提供一个示例供我们测试。@kvantour感谢comp.lang.awk家伙的提醒-它只是
ARGV[ARGC++]=ARGV[ARGC]
这是不安全的,
ARGV[ARGC++]=FILENAME
是安全的,所以我更新了我的答案以使用它。
n="$(grep -l abcd  *.txt | head -n 1)"
echo "-------- $n -------- "
cat "$n"