我正在尝试在bash脚本中编写一个函数,该脚本从stdin获取行并选出未包含在文件中的第一行。
这是我的方法:
doubles=file.txt
firstnotdouble(){
while read input_line; do
found=0;
cat $doubles |
while read double_line; do
if [ "$input_line" = "$double_line" ]
then
found=1;
break
fi
done
if [ $found -eq 0 ] # no double found, echo and break!
then
echo $input_line
break
fi
done
}
经过一些调试尝试后,我意识到当在第一个if块中将found设置为1时,它将保持其值直到下一个if块。这就是为什么它不起作用。为什么脚本的行为好像在不同的“范围”中有两个找到的变量?
第二个问题是整个方法是否可以优化。
答案 0 :(得分:1)
如评论中所示,环境变量的问题是管道中的命令(即由|
分隔的一系列命令)在子shell中运行,每个子shell都有自己的环境变量。你可以通过避免使用UUOC(无用的猫)来避免这个问题,写作:
while read ...; do ... done < "$doubles"
而不是管道。
比通过双精度文件重复使用while read
循环更快的方法是使用grep:
# Specify the file to be scanned as the first argument
firstnotdouble() {
while IFS= read -r double_line; do
if ! grep -qxF "$double_line" "$1"; then
echo "$double_line"
return
fi
done
return 1
}
在grep
:
-q
禁止打印输出,并在第一场比赛中停止-x
模式必须与整行匹配-F
pattern是一个简单的字符串而不是正则表达式。在read
:
IFS=
避免修剪空间-r
可以避免删除反斜杠使用GNU grep,您可以使用-xF -m1
(如果您喜欢隐藏-xFm1
而不是-qxF
,那么请忽略echo
。 grep扩展程序-m N
限制了找到N
的匹配数。