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“$”)
完整的单词匹配变得更加复杂,这取决于您对“单词”的定义,并且可以由特定于实现的构造提供服务,因此除非您需要,否则我将省略它。使用GNUgrep
:
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"