あるファイルを読み、別のファイルにコピー

あるファイルを読み、別のファイルにコピー

ファイルの内容をコピーし、前のコマンドの出力と一致する場合は、数行を削除する必要がある問題があります。しかし、これまではファイルラインをまったく同じに保つのに苦労しています。コピーを省略することは影響を受けない行で発生するため、問題の一部ではないかのようにスクリプトの簡単な部分があります。

たとえば、

ソースファイルには次のものがあります。

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以下を行います。

  1. 標準入力から最初のバイト(改行またはnull)を読み取り、データを変数に入れますline
  2. 行末にないバックスラッシュを削除します。二重バックスラッシュは\\単一のバックスラッシュになります。つまり、バックスラッシュは改行文字でない限り、次の文字を引用します。
  3. read改行で停止し、行末の文字がaの場合は、\バックスラッシュの改行シーケンスを削除し、読み続けながら変数に追加しますline。最初に繰り返す:前にバックスラッシュがない改行文字、入力の終わり。
  4. lineから文字で構成される最も長いサフィックスを削除します$IFS。デフォルトでは、IFSタブ、スペース、および改行が含まれているため、値の末尾からASCIIスペースが削除されますline
  5. line空白文字で構成される最も長いプレフィックスを削除します$IFS

たとえば、入力が次のような場合

 : hello\
world: :
wibble

これはインクルード(初期スペースなし)にread lineなり、デフォルトはです。 (ちょうどコロン)に変更すると、結果は(開始と終わりの空白)です。空白がすべて含まれている場合、結果は(初期または末尾の空白なし)です。line: helloworld: :IFSIFS:read line : helloworld: IFS:: helloworld

これを防ぐには、IFSnull値に設定してください(設定を解除するのとは異なります)。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入力を変更せずにそのままにするには、またはで始まる現在のディレクトリのファイルのリストに展開します。abecho 'a* b*' | IFS= read -r line; echo "$line"

また、このechoコマンドは時々印刷される文字列を変更することに注意してください。正確な方法はシェルによって異なります。一部のシェルはバックスラッシュエスケープを処理し、一部のシェルはオプションを認識します。echo文字列にバックスラッシュが含まれておらず、ダッシュ()で始まらないことがわかっている場合-にのみ、文字列をそのまま出力できます。文字列をそのまま印刷する安定した移植可能な方法

printf '%s\n' "$line"

これにより、文字列の後に改行文字が印刷されます。たとえば、上記のコマンドから改行文字を省略echoできます。\n

答え2

変数を引用:

echo "$line" >> /tmp/dest_file

関連情報