ファイルの内容をコピーし、前のコマンドの出力と一致する場合は、数行を削除する必要がある問題があります。しかし、これまではファイルラインをまったく同じに保つのに苦労しています。コピーを省略することは影響を受けない行で発生するため、問題の一部ではないかのようにスクリプトの簡単な部分があります。
たとえば、
ソースファイルには次のものがあります。
Testing, resuming text
スクリプトを実行すると、フィールドは次のようになります。
Testing, resuming text
私は次のことをしています:
#!/usr/bin/bash
rm /tmp/dest_file
while read line
do
echo $line >> /tmp/dest_file
done < $1
私が経験している問題は、タブ形式のフィールドによってファイルが異なることです。
答え1
このサイトは何度も登場しました - 参照IFSについて学ぶそして関連する問題。この回答では、何が間違っている可能性があるのか、そしてこれを防ぐ方法をまとめます。詳細については、リンクされたスレッドを参照してください。
read line
以下を行います。
- 標準入力から最初のバイト(改行またはnull)を読み取り、データを変数に入れます
line
。 - 行末にないバックスラッシュを削除します。二重バックスラッシュは
\\
単一のバックスラッシュになります。つまり、バックスラッシュは改行文字でない限り、次の文字を引用します。 read
改行で停止し、行末の文字がaの場合は、\
バックスラッシュの改行シーケンスを削除し、読み続けながら変数に追加しますline
。最初に繰り返す:前にバックスラッシュがない改行文字、入力の終わり。line
から文字で構成される最も長いサフィックスを削除します$IFS
。デフォルトでは、IFS
タブ、スペース、および改行が含まれているため、値の末尾からASCIIスペースが削除されますline
。line
空白文字で構成される最も長いプレフィックスを削除します$IFS
。
たとえば、入力が次のような場合
: hello\
world: :
wibble
これはインクルード(初期スペースなし)にread line
なり、デフォルトはです。 (ちょうどコロン)に変更すると、結果は(開始と終わりの空白)です。空白がすべて含まれている場合、結果は(初期または末尾の空白なし)です。line
: helloworld: :
IFS
IFS
:
read line
: helloworld:
IFS
:
: helloworld
これを防ぐには、IFS
null値に設定してください(設定を解除するのとは異なります)。read
コマンドを作成しなければ設定できませんIFS= read
(参照:"IFS=;"代わりに「IFS = Read」が頻繁に使用されるのはなぜですか?)。
バックスラッシュ処理を防ぐには、-r
オプションをに渡しますread
。
シェルが zsh でない場合、入力にヌルバイトがあると、後続の文字が失われます。シェルはバイナリデータを読み取るようには設計されていません。
したがって、一度に1行ずつ読み込む慣用語は次のようになります。
while IFS= read -r line; do
… # process "$line"
end
変数を使用するときは、line
次の点を確認してください。変数の置換には常に二重引用符を使用してください。:"$line"
。二重引用符がない場合、シェルは最初に変数値を展開し、次の文字が含まれるたびに値を別々の単語に分割し、IFS
各単語はワイルドカードパターンとして解釈され、一致するファイルのリストに置き換えられます(一致するものがない場合) 。ファイルでは、スキーマはそのまま残ります。したがって、echo 'a* b*' | IFS= read -r line; echo $line
入力を変更せずにそのままにするには、またはで始まる現在のディレクトリのファイルのリストに展開します。a
b
echo 'a* b*' | IFS= read -r line; echo "$line"
また、このecho
コマンドは時々印刷される文字列を変更することに注意してください。正確な方法はシェルによって異なります。一部のシェルはバックスラッシュエスケープを処理し、一部のシェルはオプションを認識します。echo
文字列にバックスラッシュが含まれておらず、ダッシュ()で始まらないことがわかっている場合-
にのみ、文字列をそのまま出力できます。文字列をそのまま印刷する安定した移植可能な方法
printf '%s\n' "$line"
これにより、文字列の後に改行文字が印刷されます。たとえば、上記のコマンドから改行文字を省略echo
できます。\n
答え2
変数を引用:
echo "$line" >> /tmp/dest_file