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
FILE1の行がFILE2にない場合は、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
通常、すべての大文字変数は予約されています。環境変数(共有ネームスペースとして環境にエクスポートされた変数)なので、シェル変数にのみ大文字変数を使用しないことをお勧めします。
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
シェルでループを使い始めるとき特にwhile read
ループ、これは通常、間違ったアプローチを取っていることを意味します。ファイルの各行に対して複数のコマンドを順次実行しますが、これはシェルスクリプトの作成方法ではありません。代わりに、特定の特殊コマンドを一度実行したいと思います。協力仕事に。
まず、POSIXシェルから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
。