:
はの別名ですtrue
。どちらもbashのシェル組み込みコマンドですが/bin/:
、aはありません/bin/true
。出力のリダイレクトにより、シェルはを使用しopen(2)
てファイルに移動しO_CREAT|O_TRUNC
ます。何も書かれていない場合、長さゼロのままです。
これらの2つの部分をまとめること:> file
は、ファイルを切り捨てるためのかなり一般的なイディオムです。: >file
しかし、ほとんどの人はを書くことで奇妙に見えないようにします。
2行目のコメントを求めたので、コメントを回答に変えます。(質問でこれを尋ねなかったとしても。)
2行目は、otherfile
いくつかの名前付き変数に行を読み込むループです。ループ本体はecho
、;
以前の空白の代わりに区切り文字を使用してそれらを印刷するために使用します。 file
リダイレクトがループ内にあるため、各反復が閉じられ、反復ごとに(追加のために)再度開かれます。を使用while ...;do read -r ...;done <otherfile >file
することで、ファイルの切り捨てが少なくなり、最初にファイルを切り捨てる必要がなくなります。エスケープ文字としてread -r
は食べません\
。
bashでのテキスト処理は非常に遅いです。その一部は避けられません。行末をオーバーシュートしないようにread
、一度に1バイト(read(2)
1バイトにつき1 システムコール)行く必要があります。ジョブに適切なツールを使用することをお勧めします。
awk -vOFS=';' '{ print $1, $2, $4, $5, $3 }' -- otherfile >file
--
というotherfile
名前の場合、スクリプトは壊れません--version
。
出力フィールド区切り;
文字を設定すると、複数のフィールドを引数として渡して印刷することができます。シェルread
は、空白を含む行全体を最後の変数に割り当てますが、awkに5つだけに分割するように指示する方法はありません。Perlはsplit
max-fields引数を取ることができるため、これを簡単にしますが、awkよりも起動がかなり遅くなります。
実際、それはそれほど難しくなく、書くのがjustい正規表現であることが判明しました。$5
awkの代わりに残りの行を取得するには、フィールドをループすると元の空白が失われます。私の最初の実行可能なアイデアは、gensub
on $0
(行全体)を使用して最初の4つのフィールド(つまり、スペースが後に続くスペース以外)を削除し、他のすべてを残すことです:
awk -vOFS=';' '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1); print $1, $2, $4, tail, $3 }' -- otherfile >file
私は最初の試みでそれを正しく理解しましたが、私がそのことに感銘を受けたという事実は、そのawkコードの可読性について何かを言います。>。<
print
以前と同じですがtail
、の代わりにあることに注意してください$5
。
echo 'A B c DD e f g f' |
awk -vOFS=\; '{ tail = gensub("[[:space:]]*([^[:space:]]+[[:space:]]+){4}", "", 1);
print $1, $2, $4, tail, $3 }'
A;B;DD;e f g f;c
リテラルをコピーして貼り付けて、出力に表示されたことを示すことができれば、これはより印象的です。^ Qを使用してbashに1つ入力します。ctrl-Qは、bashのemacsスタイルの行編集が実際のemacsと同じであるため、次のキー入力をリテラル文字として引用することを意味します。
http://mywiki.wooledge.org/BashFAQには、スクリプトで使用するデータやファイル名に関係なく壊れない方法で、スクリプトに関する有用な情報があります。
:>
は、単一の演算子ではありません。: > file
代わりに読むと理解しやすいかもしれません。