我正在尝试处理一个大文件集,将特定行附加到“test_result.txt”文件中 - 我通过以下代码实现了它 - 不是很优雅。
for i in *merged; do
while read -r lo; do
if [[ $lo == *"ID"* ]]; then
echo $lo >> test_result.txt
fi
if [[ $lo == *"Instance"* ]]; then
echo $lo >> test_result.txt
fi
if [[ $lo == *"NOT"* ]]; then
echo $lo >> test_result.txt
fi
if [[ $lo == *"AI"* ]]; then
echo $lo >> test_result.txt
fi
if [[ $lo == *"Sitting"* ]]; then
echo $lo >> test_result.txt
done < $i
done
然而,我试图使用数组来缩小它的大小 - 这导致了一次相当不成功的尝试。
KEYWORDS=("ID" "Instance" "NOT" "AI" "Sitting" )
KEY_COUNT=0
for i in *merged; do
while read -r lo; do
if [[$lo == ${KEYWORDS[@]} ]]; then
echo $lo >> ~/Desktop/test_result.txt && KEY_COUNT="`expr $KEY_COUNT + 1`"
fi
done < $i
done
答案1
看起来您想要从一组文件中获取至少包含一组单词中的一个的所有行。
假设你没有数千文件,您可以使用单个grep
命令来完成此操作:
grep -wE '(ID|Instance|NOT|AI|Sitting)' ./*merged >outputfile
这将从名称匹配的文件中提取与模式中列出的任何单词匹配的行*merged
。
with确保给定-w
的grep
字符串不作为子字符串匹配(即NOT
不会在 中匹配NOTICE
)。该选项启用模式中-E
的交替。|
-h
如果您不希望输出中包含匹配行的文件名,请将该选项添加到命令中。
如果您确实有数千个文件,则上述命令可能会由于扩展到太长的命令行而失败。在这种情况下,您可能想做类似的事情
for file in ./*merged; do
grep -wE '(ID|Instance|NOT|AI|Sitting)' "$file"
done >outputfile
grep
这将对每个文件运行一次命令,或者,
find . -maxdepth 1 -type f -name '*merged' \
-exec grep -wE '(ID|Instance|NOT|AI|Sitting)' {} + >outputfile
grep
这将一次对尽可能多的文件进行尽可能少的调用。
有关的:
答案2
添加数组并没有特别帮助:您仍然需要循环遍历数组的元素(请参阅如何测试某个项目是否在 bash 数组中?):
while read -r lo; do
for keyword in "${keywords[@]}"; do
if [[ $lo == *$keyword* ]]; then
echo $lo >> ~/Desktop/test_result.txt && KEY_COUNT="`expr $KEY_COUNT + 1`"
fi
done
done < "$i"
使用case
语句可能会更好:
while read -r lo; do
case $lo in
*(ID|Instance|NOT|AI|Sitting)*)
echo "$lo" >> ~/Desktop/test_result.txt && KEY_COUNT="`expr $KEY_COUNT + 1`"
;;
esac
done < "$i"
(我假设您在循环中对这些行进行了进一步处理。如果没有,grep 或 awk 可以更有效地完成此操作。)