将一个文件缺少的内容添加到另一个文件中

将一个文件缺少的内容添加到另一个文件中
FILE1=$1   
FILE2=$2

if [ ! -e "$FILE2" ]
then
   touch $FILE2
fi

while read line; do
  if grep -q "$line" $FILE2
  then
    echo
  else
    echo $line >> $FILE2
  fi
done < $FILE1

如果 FILE2 中不存在 FILE1 的行,我想将它们添加到 FILE2 中。我的目的是列出 FILE1 的行,如果 FILE2 中不存在这些行,则将它们添加到 FILE2 中。

怎么了?

答案1

awk 'NR == FNR {first[$0];next}; ! ($0 in first)' "$file2" "$file1" >> "$file2"

假设文件名不包含=字符。如果可以的话,在支持 /dev/fd/n 的系统上,您可以这样做:

awk 'NR == FNR {first[$0];next}; ! ($0 in first)' \
  /dev/fd/3 3< "$file2" /dev/fd/4 4< "$file1" >> "$file2"

请注意,如果行在 中多次出现$file1且不在 中出现$file2,则所有出现的情况都将附加到 中$file2。如果这不是您想要的,那么:

awk 'NR != FNR && ! ($0 in seen); {seen[$0]}' \
  /dev/fd/3 3< "$file2" /dev/fd/4 4< "$file1" >> "$file2"

如果这些行是唯一的并且您不介意输出被排序,您也可以这样做:

LC_ALL=C sort -uo "$file2" "$file1" "$file2"

至于你的代码有什么问题:

FILE1=$1   
FILE2=$2

按照惯例,所有大写变量均保留用于环境变量(导出到作为共享命名空间的环境的变量),因此最好不要将所有大写变量仅用于 shell 变量。

if [ ! -e "$FILE2" ]
then
   touch $FILE2
fi

你在 的参数中引用了它[,但没有在 的参数中引用它touch,为什么?

另外,请注意它是

touch "$file_or_option"

如果您希望变量始终被视为文件参数,您需要:

touch -- "$file2"

而且它们if ! condition; then do-something-to-make-it-true通常是不好的练习并且受到比赛条件的影响。最好这样做enforce-the-condition || die-if-couldn't。所以在这里:

touch -- "$file2" || exit

但无论如何,>>重定向将创建该文件(如果不能,则返回错误)。

while read line; do

当您开始在 shell 中使用循环时特别是while read循环,那么这通常意味着您采用了错误的方法。您将为文件的每一行顺序运行多个命令,这不是 shell 脚本编写的方式。相反,您想运行一次一些专门的命令合作到任务。

首先,要在 POSIX shell 中读取 a line,语法是

IFS= read -r line

不是 read line

  if grep -q "$line" $FILE2

再说一次,它是:

grep -q "$option_or_regexp"

或者:

grep -q -- "$regexp"

或者:

grep -qe "$regexp"

如果您想搜索字符串而不是匹配正则表达式,则需要该-F选项,如果您想匹配整个行,则需要-x.所以:

grep -qxFe "$line" < "$file2"
  then
    echo
  else
    echo $line >> $FILE2

同样,您将 split+glob 运算符应用于 的内容$line(如果不在 sh 模式下$FILE2使用,则应用于bash)。

此外,echo不能用于任意数据。你需要:

printf '%s\n' "$line" >> "$file2"

这里。但是,为循环中的每次传递重新打开是一种浪费,$file2而您本来可以在整个循环中完成一次。

  fi
done < $FILE1

再次:

done < "$file1"

如果使用bash.

相关内容