web-dev-qa-db-ja.com

read、head -1、sed 1qの間に違いはありますか?

次のコマンドはほぼ同等のようです。

read varname
varname=$(head -1)
varname=$(sed 1q)

1つの違いは、readはシェルの組み込みであり、headsedはそうではないということです。

それ以外に、3つの動作に違いはありますか?

私の動機は、シェルとhead,sedなどの主要ユーティリティのニュアンスをよりよく理解することです。たとえば、headの使用がreadの簡単な置き換えである場合、なぜreadが組み込みとして存在するのですか?

7
Tyler

効率も組み込み性も最大の違いではありません。それらのすべては、特定の入力に対して異なる出力を返します。

  • head -n1は、入力に改行がある場合にのみ、末尾の改行を提供します。

  • sed 1qは常に後続の改行を提供しますが、それ以外の場合は入力を保持します。

  • readは後続の改行を提供せず、バックスラッシュシーケンスを解釈します。

さらに、readには、分割、タイムアウト、入力履歴などの追加オプションがあり、それらの一部は標準であり、その他はシェル間で異なります。

6
o11c

1つには、行全体をとるのではなく、読み取りでテキストを解析できます

echo "foo:bar:baz" | {
  IFS=: read one two three
  echo $two
}
5
glenn jackman

ビルトインは、システムコールをより高速にする方法として存在します。ですから、readコマンドは、より効率的になる組み込みとして存在していると思います。

ここ からの引用、

これらの組み込みコマンドはシェルの一部であり、シェルのソースコードの一部として実装されます。シェルは、実行するように要求されたコマンドが組み込みコマンドの1つであることを認識し、別の実行可能ファイルを呼び出さずに、独自にそのアクションを実行します。基本セットには多くのオーバーラップがありますが、シェルによってビルトインは異なります。

ここで、readがShellビルトインとして存在する理由を理解できるように、これを自分で試してみたいと思います。

通常、Shellビルトインではstraceを実行できませんでした。ただし、これには回避策もあります。これは answer でかなりきれいに説明されています。

  1. 最初のシェルで、コマンドをstty -echoとして実行します。
  2. 別のシェルを開き、cat | strace bash > /dev/nullとしてコマンドを実行します。
  3. これで、シェルはユーザーがコマンドを入力するのを待っており、ユーザーがコマンドを入力すると、システムレベルで何が起こっているかを確認できます。
  4. 上記の3つのコマンドを実行すると、readのシステムコールが残りの2つのコマンドよりも少ないことがわかります。 straceの出力はかなり大きいため、貼り付けていません。
5
Ramesh

Read varnameはシェルスクリプト内でのみ使用できますが、他の2つはシェルスクリプトを記述せずに使用できます。

例えば:

varname=$(head -1)varname=$(sed 1q)をターミナルのコマンドとして使用できますが、引数、つまり参照しているファイルの最上行、つまりvarnam=$(head -1 file1)を指定する必要があります。

0
Pranav Tyagi