ファイル名引数またはstdinからの入力を受け入れるスクリプトを作成するにはどうすればよいですか?
たとえば、less
この方法を使用できます。実行することができless filename
、同等にcat filename | less
。
そうするための簡単な「すぐに使える」方法はありますか?または、ホイールを再発明し、スクリプトに少しロジックを書く必要がありますか?
ファイル名引数またはstdinからの入力を受け入れるスクリプトを作成するにはどうすればよいですか?
たとえば、less
この方法を使用できます。実行することができless filename
、同等にcat filename | less
。
そうするための簡単な「すぐに使える」方法はありますか?または、ホイールを再発明し、スクリプトに少しロジックを書く必要がありますか?
回答:
ファイルの引数がスクリプトの最初の引数である場合、引数($1
)があり、ファイルであることをテストします。それ以外の場合は、stdinからの入力を読み取ります-
したがって、スクリプトには次のようなものを含めることができます。
#!/bin/bash
[ $# -ge 1 -a -f "$1" ] && input="$1" || input="-"
cat $input
たとえば、次のようにスクリプトを呼び出すことができます
./myscript.sh filename
または
who | ./myscript.sh
スクリプトの説明を編集します。
[ $# -ge 1 -a -f "$1" ]
-少なくとも1つのコマンドライン引数($# -ge 1
)AND(-a演算子)最初の引数がファイルの場合(-fは「$ 1」がファイルかどうかをテストします)、テスト結果はtrueです。
&&
シェルの論理AND演算子です。テストがtrueの場合、ファイルを割り当てinput="$1"
てcat $input
出力します。
||
シェルの論理OR演算子です。テストが偽の場合、次のコマンド||
が解析されます。入力は「-」に割り当てられます。コマンドcat -
はキーボードから読み取ります。
要約すると、スクリプト引数が提供され、それがファイルである場合、変数入力はファイル名に割り当てられます。有効な引数がない場合、catはキーボードから読み取ります。
&& input="$1" || input="-"
、なぜそれがtest
オペレーターの外にあるのですか?
$@
)がある場合はどうなりますか?
read
標準入力から読み取ります。ファイル(./script <someinput
)またはパイプ(dosomething | ./script
)からリダイレクトしても、動作は変わりません。
あなたがしなければならないのは、入力のすべての行をループすることです(そして、それはファイルの行の繰り返しと違いはありません)。
(サンプルコード、1行のみを処理します)
#!/bin/bash
read var
echo $var
標準入力の最初の行(<
または|
)をエコーします。
使用する予定のシェルについては触れないので、bashを想定しますが、これらはシェル全体でかなり標準的なものです。
引数には変数を介してアクセスできます$1
- $n
($0
プログラムの実行に使用されるコマンドを返します)。たとえば、cat
n個のファイルを区切り文字で区切って出力するスクリプトがあるとします。
#!/usr/bin/env bash
#
# Parameters:
# 1: string delimiter between arguments 2-n
# 2-n: file(s) to cat out
for arg in ${@:2} # $@ is the array of arguments, ${@:2} slices it starting at 2.
do
cat $arg
echo $1
done
この場合、ファイル名をcatに渡します。ただし、ファイル内のデータを(明示的に書き込みおよび書き換えせずに)変換する場合は、ファイルの内容を変数に保存することもできます。
file_contents=$(cat $filename)
[...do some stuff...]
echo $file_contents >> $new_filename
stdinから読み取る限り、ほとんどのシェルにはかなり標準的なread
ビルトインがありますが、プロンプトの指定方法には(少なくとも)違いがあります。
Bashの組み込みコマンドのmanページはのかなり簡潔な説明がありますread
が、私は好むバッシュハッカーのページを。
単に:
read var_name
複数の変数を設定するには、複数のパラメーター名を指定するだけですread
:
read var1 var2 var3
read
次に、stdinから1つの単語を各変数に配置し、残りのすべての単語を最後の変数にダンプします。
λ read var1 var2 var3
thing1 thing2 thing3 thing4 thing5
λ echo $var1; echo $var2; echo $var3
thing1
thing2
thing3 thing4 thing5
入力される単語が変数よりも少ない場合、残りの変数は空になります(以前に設定されていても)。
λ read var1 var2 var3
thing1 thing2
λ echo $var1; echo $var2; echo $var3
thing1
thing2
# Empty line
私-p
はプロンプトに頻繁にフラグを使用します:
read -p "Enter filename: " filename
注:ZSHおよびKSH(およびおそらく他)は、プロンプトに異なる構文を使用します。
read "filename?Enter filename: " # Everything following the '?' is the prompt
これは、実際にはread
トリックではありませんが、と組み合わせて頻繁に使用しread
ます。例えば:
read -p "Y/[N]: " reply
reply=${reply:-N}
基本的に、変数(応答)が存在する場合、それ自体を返しますが、空の場合、次のパラメーター(「N」)を返します。
最も簡単な方法は、stdinを自分でリダイレクトすることです。
if [ "$1" ] ; then exec < "$1" ; fi
または、より簡潔な形式を好む場合:
test "$1" && exec < "$1"
これで、スクリプトの残りの部分は標準入力から読み取ることができます。もちろん、ファイル名の位置をとしてハードコーディングするのではなく、より高度なオプション解析で同様に行うことができます"$1"
。
exec
ここで必要なものではないコマンドとして引数を実行しようとします。
if [ "$1" ] ; then exec < "$1" ; fi
テストスクリプトをコピーすると、コマンドが不明であるためエラーメッセージが表示されます。簡潔な形式でも同じです。
既にこのように動作する他の何かを使用(またはチェーン)し、使用します "$@"
テキスト内のスペースの実行をタブに置き換えるツールを書きたいとしましょう
tr
これを行う最も明白な方法ですが、stdin のみを受け入れるため、次のようにチェーンする必要がありcat
ます。
$ cat entab1.sh
#!/bin/sh
cat "$@"|tr -s ' ' '\t'
$ cat entab1.sh|./entab1.sh
#!/bin/sh
cat "$@"|tr -s ' ' '\t'
$ ./entab1.sh entab1.sh
#!/bin/sh
cat "$@"|tr -s ' ' '\t'
$
使用されているツールがすでにこのように動作している例では、sed
代わりにこれを再実装できます。
$ cat entab2.sh
#!/bin/sh
sed -r 's/ +/\t/g' "$@"
$
次のこともできます。
#!/usr/bin/env bash
# Set variable input_file to either $1 or /dev/stdin, in case $1 is empty
# Note that this assumes that you are expecting the file name to operate on on $1
input_file="${1:-/dev/stdin}"
# You can now use "$input_file" as your file to operate on
cat "$input_file"
bashで、よりきちんとしたパラメータ置換のトリックについては、これを。
uglifyjs < /dev/stdin
していますが、うまく機能します!
シンプルに保ち、このコードを使用することもできます
このコードを使用してスクリプトファイルpass_it_on.shを作成すると、
#!/bin/bash
cat
走れます
cat SOMEFILE.txt | ./pass_it_on.sh
また、stdinのすべてのコンテンツが画面に出力されるだけです。
または、このコードを使用して、stdinのコピーをファイルに保存してから、画面に出力します。
#!/bin/bash
tmpFile=`mktemp`
cat > $tmpFile
cat $tmpFile
ここに説明されている別の例があります。
http://mockingeye.com/blog/2013/01/22/reading-everything-stdin-in-a-bash-script/
#!/bin/bash
VALUE=$(cat)
echo "$VALUE"
楽しんで。
RaamEE