获取不在文件中的第一行stdin

时间:2015-05-14 22:40:59

标签: bash

我正在尝试在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块。这就是为什么它不起作用。为什么脚本的行为好像在不同的“范围”中有两个找到的变量?

第二个问题是整个方法是否可以优化。

1 个答案:

答案 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的匹配数。