0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

行の先頭または末尾に文字列を加えるUnixコマンド

Last updated at Posted at 2024-08-06

ファイルやlsのような行単位の出力に対し、先頭または末尾に文字列を加えるUnixな方法がいくつかあるか、考えてみました。

次の3行のファイルを考えます(以下、file=requirements.txt)。

pykakasi
opencv-python
requests

これら行にpip show␣という文字列を先頭に加えます(以下、prepend="pip show␣")。

pip show pykakasi
pip show opencv-python
pip show requests

先頭も末尾もコード的にはたいして変わりません。後尾に加える文字列は$appendにあるとします。

sed

行単位の編集ならやはりsedが王道です。行頭を正規表現の^で示すのがポイントです。

$ cat $file | sed "s/^/$prepend/"

末尾なら$です。

$ cat $file | sed "s/$/$append/"

awk

あるいはawk(3人ともご存命のようでなによりです)。行単位の処理の{}の中でシェル変数を参照するのに-vオプションを併用するのがポイントです。

$ cat $file | awk -v prepend="$prepend" '{print prepend$0}'

末尾にするならprintの引数を入れ替えます。

$ cat $file | awk -v append="$append" '{print $0append}'

while + echo

行単位でループしてechoで出力をいじるストレートな解法が、実は一番わかりやすいかもしれません。

$ cat $file | while read line; do echo $prepend$line; done

こちらも、末尾にするならechoの引数の順序を入れ替えます。

while + printf

echoの代わりにprintfを使う手もあります。上記とたいして変わりませんが。

$ cat $file | while read line; do printf "$prepend%s\n" $line; done

for + echo

whileではなくforを使う手もあります。この場合、コマンド先頭でデータを用意してきたこれまでのパターンとはちょっと違うのが(本人的には)マイナス点です。

for line in `cat $file`; do echo $prepend$line; done

xargs

行を行として出力するのに、複数行を1行にまとめるxargsをわざわざ使うのは病気と言わざるを得ませんが、まぁ、やってできないことはないわけです。

$ cat $file | xargs -L 1 echo $prepend

末尾にするのはechoではしんどいので、printfを使います。

$ cat $file | xargs -L 1 printf "%s$append\n"

jq

さらに病が高じると、JSONパーザーのjqなんかでやってしまいたくなるわけです。

入力がJSONではないという禁忌を回避しなければならないため、オプションに-r--raw)、-s--slurp)、-R--raw-input)を併用します。また、シェル変数を内部で展開させるため、--argオプションでjqの変数に置き換えるというめったに使わない技まで使います。フィルタを二重引用符でくくれればそんな手間はかからないのですが、フィルタ内部の二重引用符をいちいちエスケープすると読みにくくていけません。

$ cat $file | jq --arg prepend "$prepend" -rsR 'rtrimstr("\n") | split("\n")[] | $prepend + .'

末尾版は、ここでも最後の出力部分の順序を入れ替えるだけです。

jqの書籍は2冊出ていますが(『jqハンドブック』と『jqクックブック』)、どちらもこんな技は書いてないですね。

perl

最近では使い手も減ってきましたが、こういうワンライナーはやっぱりperlです。

while(<FILE>)を仮定する-nオプションと、それに加えて$_を自動で出力する-pオプションは相変わらず強力です(これを見せるほど追い詰められたのは80年ぶりです)。まぁ、sedの解法と変わらないですが。

$ cat $file | perl -pe "s/^/$prepend/"

sed同様、末尾なら$です。

おわりに

まだまだ解法があるような気もしますが、まぁ、こんなもんです。NodeやPythonを使った手もあるでしょうが、長くなるので、シェルな雰囲気ではなく、やめておきました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?