使用bash脚本,我试图遍历一个只有大约700个单词的文本文件,逐行遍历,并在当前目录中使用特定文件上的不区分大小写的grep搜索。为了分解它,我尝试将以下内容输出到一个文件中:
例如,如果我有这个list.txt:
search1
search2
我希望results.txt是:
search1:
grep result here
search2:
grep result here
在整个堆栈交换过程中,我找到了一些关于如何做到这一点的答案,并提出了以下实现:
#!/usr/bin/bash
while IFS = read -r line;
do
"\n$line:\n" >> "results.txt";
grep -i "$line" *.in >> "results.txt";
done < "list.txt"
然而,由于某些原因(以及我尝试过的众多变体)无法工作。似乎微不足道,但我会一直令我难以置信。任何帮助都是非常感谢的。
发布于 2018-03-16 04:07:38
如果将脚本更改为:
while IFS= read -r line; do
printf '\n%s:\n' "$line"
grep -i "$line" *.in
done < list.txt > results.txt
但它会非常慢。请参阅https://unix.stackexchange.com/questions/169716/why-is-using-a-shell-loop-to-process-text-considered-bad-practice,了解为什么在编写shell循环之前,您应该考虑很长时间,然后才能操作文本。操纵文本的标准UNIX工具是awk:
awk '
NR==FNR { words2matches[$0]; next }
{
for (word in words2matches) {
if ( index(tolower($0),tolower(word)) ) {
words2matches[word] = words2matches[word] $0 ORS
}
}
}
END {
for (word in words2matches) {
print word ":" ORS words2matches[word]
}
}
' list.txt *.in > results.txt
当然,上面的内容没有经过测试,因为您没有提供我们可以进行测试的示例输入/输出。
发布于 2018-03-15 23:20:43
可能出现的问题:
/bin/bash
路径而不是/usr/bin/bash
' '
后的IFS
-e
选项处理转义字符(此处:'\n'
)请尝试使用以下脚本:
#!/bin/bash
while IFS= read -r line; do
echo -e "$line:\n" >> "results.txt"
grep -i "$line" *.in >> "results.txt"
done < "list.txt"
发布于 2018-03-16 00:52:55
甚至不需要为此目的编写bash脚本:
输入文件:
$ more file?.in
::::::::::::::
file1.in
::::::::::::::
abc
search1
def
search3
::::::::::::::
file2.in
::::::::::::::
search2
search1
abc
def
::::::::::::::
file3.in
::::::::::::::
abc
search1
search2
def
search3
模式文件:
$ more patterns
search1
search2
search3
CMD:
$ grep -inf patterns file*.in | sort -t':' -k3 | awk -F':' 'BEGIN{OFS=FS}{if($3==buffer){print $1,$2}else{print $3; print $1,$2}buffer=$3}'
输出:
search1
file1.in:2
file2.in:2
file3.in:2
search2
file2.in:1
file3.in:3
search3
file1.in:4
file3.in:5
EXPLANATIONS:
grep -inf patterns file*.in
将grep所有file*.in与所有模式位于模式文件中感谢-f
选项,使用-i
强制不敏感大小写,-n
将添加行号sort -t':' -k3
使用第三列对输出进行排序,以便将模式重新组合在一起awk -F':' 'BEGIN{OFS=FS}{if($3==buffer){print $1,$2}else{print $3; print $1,$2}buffer=$3}'
然后awk
将打印您想要的显示,方法是使用:
作为字段分隔器和输出字段分隔器,使用缓冲区变量保存模式(第三个字段),并在模式更改时打印模式($3!=buffer
)。https://stackoverflow.com/questions/49314856
复制