bashのこの奇妙な記号「:>」はどういう意味ですか


47

スクリプトで何かを見つけましたが、メインスクリプトに属していません。あった:>ラインに。

それが何を意味するのか説明してもらえますか?

:> file
while read A B C D E; do echo "$A;$B;$D;$E;$C" >> file; done < otherfile

6
重要なの:>は、単一の演算子ではありません。: > file代わりに読むと理解しやすいかもしれません。
jpfx1342

これは、スクリプトを書いている人がループの出力をファイルにリダイレクトする必要があることを意味しますwhile read A B C D E; do echo "$A;$B;$D;$E;$C"; done < otherfile > file。または、Peterが提案したように、仕事に適切なツールawkを使用する必要がありました。余談ですが、ほとんどの場合、-rスイッチはで使用しreadます。
トム・フェネシュ

bashの外では、カラスにとってスマイリーになります。
smci

回答:


46

bashスクリプトの行に:>がありました。どういう意味ですか?

:> file

それは言うことの近道です:

  • file存在しない場合は作成し、それ以外の場合は0バイトに切り捨てます。

これはfile、それが存在し、空であることを確認できることを意味します。

使用することもできます> file:> file、よりポータブルです。

スタックオーバーフローの質問を参照してください':'(コロン)GNU Bash Builtinの目的は何ですか?詳細については。


二行目がわかりません。読んだ変数を読むと思った。コマンドエコーも奇妙です。説明してもらえますか?
diego9403

私はUnixの専門家ではないが、私は二行目から物事を読み込んだと思うotherfileし、echoそれらを出よfile。また、読み取ったものから変数を作成します...明確な答えが必要な場合は、独自の質問をしてください。
DavidPostill

2
@ diego9403:readstdinから入力を取得します。それ自体で、入力した内容が読み取られます。stdinはリダイレクトされているため<otherfile、その内容はotherfilestdinに「入力」されます。したがってread、値を1行ずつ変数$ A、$ B、$ C、$ D、および$ Eに取得します。
スリーブマン

それではtruncate、coreutilsからのより曖昧な代替物にすぎませんか?
フェデリコポロニ

1
@PeterCordes私は「それは一般的ではない」のように「あいまいな」という意味ではなく、「読者にはわかりにくい」という意味でした。
フェデリコポロニ

29

新しいファイルを作成するためのおしゃれな方法のように見えます。In bash :はヌルコマンドです。

$ type : 
: is a shell builtin 
$ help : 
:: :
    Null command.

    No effect; the command does nothing.

    Exit Status:
    Always succeeds.

>の出力を:ファイルにリダイレクトします。


2
また、ファイルが既に存在する場合は切り捨てられます...
DavidPostill

2
はい、これは何である>
はArkadiusz Drabczyk

2
:はの省略形ですtrue。おそらくいくつかのシェルでtrue、組み込みではありませんか?どちらもbashに組み込まれています。
ピーターコーデス

12

:はの別名です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はsplitmax-fields引数を取ることができるため、これを簡単にしますが、awkよりも起動がかなり遅くなります。

実際、それはそれほど難しくなく、書くのがjustい正規表現であることが判明しました。$5awkの代わりに残りの行を取得するには、フィールドをループすると元の空白が失われます。私の最初の実行可能なアイデアは、gensubon $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には、スクリプトで使用するデータやファイル名に関係なく壊れない方法で、スクリプトに関する有用な情報があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.