grep a* といった
grepのパターンに*が含まれているとgrepに渡す前にbashがワイルドカードと解釈してカレントディレクトリにあるファイル名に展開してしまうので期待道理に動かないよという話。
echo *を実行してみると理屈がよくわかると思う。
grep "a*" のように常に引用符で括る癖をgrepに限らずつけたほうが良い。
2016年6月26日日曜日
2016年6月16日木曜日
シェルスクリプトで文字列を結合する
How to concatenate strings in shell script?
input file: input.txt
foo
bar
expected results: output.txt
foo_awesome
bar_awesome
STR=_awesome
cat input.txt | xargs -n1 -d'\n' printf "%s %s\n" $STR | awk '{printf "%s%s\n", $2, $1}' > output.txt
Isn't it awesome?
解説
catでファイル内容を読み込みその内容とSTR変数をxargsを使いprintfの引数として渡す。
つまりprintf "%s %s\n" _awesome fooが一番目に呼ばれることになる。空白を挟んで _awesome foo という行を作り出し標準出力している。本当はここで整形を済ませたいがprintfコマンドが引数の順序を指定できず自由度が低いためawkのprintfで本格的に整形している。そして標準出力をファイルにリダイレクトして完了。
2 string variables version.
expected results: output.txt
prefoo_awesomeSTR2=pre
prebar_awesome
STR=_awesome
cat input.txt | xargs -n1 -d'\n' printf "%s %s %s\n" $STR $STR2 | awk '{printf "%s%s%s\n", $2, $3, $1}' > output.txt
Shell script commandの根本的な解説
シェルスクリプトのコマンドがわかりにくい一因はその入出力方法が分かりにくいからであり、それさえ理解できればあとはなんとかなります。コマンド自体はただのC言語などで書かれたプログラムであり入出力方法の数はプログラムで可能な数だけありうるのです。
よく使われる入力方法としては
出力方法としては
では次のコマンドを例に解説していきます。
cat foo.txt | sort
まずcatコマンドの引数として foo.txt を入力しています。そしてcatコマンドはその引数を元にファイル内容を読み込み標準出力へと出力します。そして | パイプで接続され標準出力の内容が次のプログラムsortへ標準入力として渡されます。sortは引数がなければ標準入力の内容をソートして標準出力へと出力します。そしてsortの標準出力の内容はこの後に何も指定していないため画面へと出力されます。
次のように
cat foo.txt | sort > out.txt
> リダイレクトを使用することで標準出力の内容をファイルへと出力することができます。(この場合 out.txtはsortの引数として渡しているわけではありません。|や>はシェルの機能です。)
プログラム自体がファイルを直接出力するというパターンもあります。
gcc main.c -o app
gccコンパイラに引数としてmain.c -o appを渡しています。gccはmain.cファイルを読み込みコンパイルした内容をappという名前のファイルへ出力します。
さて入力方法としては引数と標準入力が主に使われていることがわかりました。またファイルとしての入力は引数でファイル名を指定して読み込むというパターンが多いこともわかりました。出力方法としては基本的に標準出力が使われていることもわかりました。標準出力は| パイプで接続すれば次の標準入力になることはわかりましたが、後続のコマンドの引数として入力するにはどうしたら良いのでしょうか。それにはxargsを使いましょう。
input.txt:
file1
file2
file3
cat input.txt | xargs cat
xargsは標準入力から渡された文字列をxargsの引数として渡されたcatの引数として呼び出します。つまりxargsは cat file1 file2 file3を呼び出します。catは複数のファイル名が引数として渡された場合はその内容を結合してから標準出力へ出力します。つまり上記コマンドはinput.txtに書かれているファイル名を読み込みそのファイル内容をすべて結合して画面に表示します。xargs -n1 catと指定すればcatに引数を最大1個だけ付加して呼び出します。つまりcat file1、cat file2、cat file3と3回に分けてcatが呼びだされます。catコマンドの場合は分割したところで出力結果は同じですが。
引数の指定方法によって入力元や出力先を変化させることのできるコマンドはよくあります。
また多くのUNIXプログラムはファイル名を指定する部分に - を指定することでファイルの代わりに標準入力(または標準出力)を使用できます。
echo "int main(){}" | g++ -x c++ -
よく使われる入力方法としては
標準入力があり
プログラム引数
ファイル
出力方法としては
標準出力があります。 入出力ともにネットワーク、プロセス間通信 etc などがありえます。
標準エラー出力 (コマンドの成否を表すメッセージなど)
ファイル
プログラムの戻り値(整数で正常終了した場合は普通0が返される)
では次のコマンドを例に解説していきます。
cat foo.txt | sort
まずcatコマンドの引数として foo.txt を入力しています。そしてcatコマンドはその引数を元にファイル内容を読み込み標準出力へと出力します。そして | パイプで接続され標準出力の内容が次のプログラムsortへ標準入力として渡されます。sortは引数がなければ標準入力の内容をソートして標準出力へと出力します。そしてsortの標準出力の内容はこの後に何も指定していないため画面へと出力されます。
次のように
cat foo.txt | sort > out.txt
> リダイレクトを使用することで標準出力の内容をファイルへと出力することができます。(この場合 out.txtはsortの引数として渡しているわけではありません。|や>はシェルの機能です。)
プログラム自体がファイルを直接出力するというパターンもあります。
gcc main.c -o app
gccコンパイラに引数としてmain.c -o appを渡しています。gccはmain.cファイルを読み込みコンパイルした内容をappという名前のファイルへ出力します。
さて入力方法としては引数と標準入力が主に使われていることがわかりました。またファイルとしての入力は引数でファイル名を指定して読み込むというパターンが多いこともわかりました。出力方法としては基本的に標準出力が使われていることもわかりました。標準出力は| パイプで接続すれば次の標準入力になることはわかりましたが、後続のコマンドの引数として入力するにはどうしたら良いのでしょうか。それにはxargsを使いましょう。
input.txt:
file1
file2
file3
cat input.txt | xargs cat
xargsは標準入力から渡された文字列をxargsの引数として渡されたcatの引数として呼び出します。つまりxargsは cat file1 file2 file3を呼び出します。catは複数のファイル名が引数として渡された場合はその内容を結合してから標準出力へ出力します。つまり上記コマンドはinput.txtに書かれているファイル名を読み込みそのファイル内容をすべて結合して画面に表示します。xargs -n1 catと指定すればcatに引数を最大1個だけ付加して呼び出します。つまりcat file1、cat file2、cat file3と3回に分けてcatが呼びだされます。catコマンドの場合は分割したところで出力結果は同じですが。
入力元 | 出力先 | 利用可能なコマンド |
---|---|---|
ファイル | 標準出力 | cat |
引数 | 標準出力 | echo、printf |
標準入力 | 引数 | xargs |
ネットワーク | ファイル | wget |
ネットワーク | 標準出力 | curl |
入力元 | 出力先 | シェルの機能 |
---|---|---|
標準出力 | 標準入力 | | |
標準出力 | 画面 | そのまま |
標準エラー出力 | 画面 | そのまま |
標準出力 | ファイル | > |
標準エラー出力 | 標準出力 | 2>&1 |
引数の指定方法によって入力元や出力先を変化させることのできるコマンドはよくあります。
入力元 | 出力先 | コマンド | 解説 |
---|---|---|---|
標準入力 | 標準出力 | grep パターン | 引数として渡したパターンを標準入力から検索し標準出力へ出力する |
引数のファイル名 | 標準出力 | grep パターン ファイル名 | 引数として渡したパターンをファイルから検索し標準出力へ出力する |
また多くのUNIXプログラムはファイル名を指定する部分に - を指定することでファイルの代わりに標準入力(または標準出力)を使用できます。
echo "int main(){}" | g++ -x c++ -
登録:
投稿
(
Atom
)