Output
echo
- -n : 改行なし
- -e : エスケープシーケンス有効化
- -x : カラーコード指定
$ echo -n "hello"
$ echo "hello"
hello
$ echo -e "\thelloo\b"
hello
$ COL_BLUE="\x1b[34;01m"
$ COL_RESET="\x1b[39;49;00m"
$ echo -e $COL_BLUE"Important Message: "$COL_RESET"This is a message"
> Important Message: が紫になる
printf
フォーマット可能。デフォルトではechoと違って改行が無い
$ printf hello
hello$ printf "hello\n"
hello
$ printf "hello %s, how are you?" $USER
hello ushio, how are you?$
C言語系のprintfと違って、パラメータが複数あると、複数回実行される様子。
$ printf "p%st\n" a e i o u
pat
pet
pit
pot
put
しかし、2つの%s
を持っていると、ちゃんと置き換えられる様子。
$ printf "Hell%s %sorld! %s\n" o W $USER
Hello World! ushio
とても柔軟%sが足りなくなったら自動的に繰り返すっぽい。
$ printf "*%20s *%20s *%20s *\n" $(ls)
* Applications * Apps * Codes *
* Desktop * Documents * Downloads *
* Dropbox * Library * Movies *
* Music * OneDrive * OneDrive *
* - * Microsoft * Pictures *
* Public * aaa.jpg * bin *
* dev * foonotes.txt * go *
* google-cloud-sdk * istio.yaml * lib *
* node_modules * package-lock.json *
-v
のスイッチで、変数に代入することもできる
$ printf -v hello "hello %s, nice to meet you! \n" $USER
$ echo $hello
hello ushio, nice to meet you!
Input
read
$REPLY
read は文字を読み込むコマンド。デフォルトでは$REPLY
という変数に代入される。
$ read; echo $REPLY
hello
hello
-r
-r
オプションは、エスケープシーケンスを無くして、Rawで出力する。入力の際は、エスケープシーケンスがかかると不思議な挙動になるので、常にこのオプションがオススメ
$ read; echo $REPLY
\\
\
$ read -r; echo $REPLY
\ is ok for now
\ is ok for now
-n, -s
-n
は何文字の入力を待つかというフラグで、-s
は入力した文字をエコーするか否かのスイッチ。次のプログラムを作ってみる。
#!/bin/bash
echo -n "Annie Are you OK? (Y/N)? "
answered=
while [[ ! $answered ]]; do
read -r -n 1 -s answer
if [[ $answer = [Yy] ]]; then
answered="I'm relieved"
elif [[ $answer = [Nn] ]]; then
answered="Annie are you OK?"
fi
done
printf "\n%s\n" "$answered"
結果は予想通りで次の通り。実際にプログラムを作る時に、最初は、printf "\n%s\n" $answered
だったのですが、それだと、スペースがあると実行が2回繰り返されるので、ダブルクオートで囲っています。
$ ./answer
Annie Are you OK? (Y/N)?
I'm relieved
$ ./answer
Annie Are you OK? (Y/N)?
Annie are you OK?
parameter
パラメータをとると、それを変数にして代入してくれる。次の実験でわかるように、2つのパラメータがあると、スペースで分割された内容をそれぞれに代入してくれる。
$ read a b
hello world
$ echo $a $b
hello world
足りない場合、より多い場合は次の挙動
$ read a b
hello
$ echo $a
hello
$ echo $b
$ read a b
hello world tsuyoshi
$ echo $a $b
hello world tsuyoshi
$ echo $a
hello
$ echo $b
world tsuyoshi
IFS
IFS (Internal Field Separator) はワードを分割するのに使われる。デフォルトは、。変更する場合は、変数に代入すれば良い。
$ IFS=: read a b
hello:world
$ echo $a $b
hello world
ちなみに、;
をデリミタにすると動かなかった。これは、IFSというより、シェルが改行と思うからだと思う。
$ IFS=; read a b
hello;world
$ echo $a $b
hello;world
Standard Streams
Bashには3つのストリームが存在する。
- 0: Standard Input (stdin)
/dev/stdin - 1: Standard Output (stdout)
/dev/stdout - 2: Standard Error (stderr)
/dev/stderr
エラーは、エラーメッセージや診断に使われる。
/dev/null は全てのデータを取り除く。
Redirection
Input redirection: <
入力を標準入力以外にします。例えばファイルとか。例えば startup.sh の全ての行から azure
に関する行を抜き出すには下記の通りです。
$ grep azure < startup.sh
git clone https://github.com/Azure-Samples/openhack-devops-proctor.git /home/azureuser/openhack-devops-proctor
# RUN chown azureuser:azureuser -R /home/azureuser/openhack-devops-proctor/.
cd /home/azureuser/openhack-devops-proctor
cd /home/azureuser
install -b /home/azureuser/openhack-devops-proctor/provision-team/kvstore.sh /usr/local/bin/kvstore
echo 'export KVSTORE_DIR=/home/azureuser/team_env/kvstore' >> /home/azureuser/.bashrc
cd /home/azureuser/openhack-devops-proctor/provision-team
PATH=$PATH:/opt/mssql-tools/bin KVSTORE_DIR=/home/azureuser/team_env/kvstore ./setup.sh -i $SUBID -l $LOCATION -n $TEAMNAME -u "$AZUREUSERNAME" -p "$AZUREPASSWORD" -r "$RECIPIENTEMAIL" -c "$CHATCONNECTIONSTRING" -q "$CHATMESSAGEQUEUE" -t "$TENANTID" -a "$APPID" 2>&1 | tee -a /home/azureuser/logs/teamdeploy.out
Output redirection: >
下記のコマンドで、ls.txtに ls man
の内容が保存されます。この場合、既存のファイルがあると上書きされます。Append mode で書き出ししたい場合は >>
を使うと、既存の内容は残したまま追記されます。
$ man ls > ls.txt
Pipes
パイプは、最初のコマンドの出力を次のコマンドの入力にします。man ls
の内容を次のgrep directory
に渡して実行します。
$ man ls | grep directory
ls -- list directory contents
For each operand that names a file of a type other than directory, ls
each operand that names a file of type directory, ls displays the names
of files contained within that directory, as well as any requested, asso-
If no operands are given, the contents of the current directory are dis-
played. If more than one operand is given, non-directory operands are
displayed first; directory and non-directory operands are sorted sepa-
-a Include directory entries whose names begin with a dot (.).
directory, an asterisk (`*') after each that is executable, an at
directory the link references rather than the link itself. This
name. In addition, for each directory whose contents are displayed, the
total number of 512-byte blocks used by the files in the directory is
files in the directory. If the file or directory has extended
a '@' character. Otherwise, if the file or directory has extended secu-
x The file is executable or the directory is search-
1. directory
10. directory writable to others, with sticky bit
11. directory writable to others, without sticky
is a symlink that resolves to a non-directory file, the output wil
Stream のリダイレクト N>
例えば次のリダイレクトは、エラー出力をを無くす。
cmd 2> /dev/null
他の Stream へのリダイレクト >&N
標準出力をエラー出力にリダイレクト
>&2 or 1>&2
標準エラー出力を標準出力に
2>&1
標準出力とエラー出力を同じファイルに送る
cmd > logfile 2>&1
この書き方はうまくいかない
cmd > logfile 2> logfile
ログファイルが上書き保存されてしまうので中途半端になる。
下記の表現は使わないこと。Depricated.
&> >&
順番は重要
この場合は同じ
cmd < inputfile > outputfile
> outputfile cmd < inputfile
最初のだと、エラーがログファイルにはかれるが、二番目は、エラーが標準出力にはかれる。
cmd > logfile 2>&1
2>&1 >logfile cmd
output.sh
#!/bin/bash
echo "This is standard output" > /dev/stdout
echo "This is standard error" > /dev/stderr
実行結果
$ ./output.sh > logfile 2>&1
invincible:Bash ushio$ cat logfile
This is standard output
This is standard error
$ ./output.sh 2> /dev/null
This is standard output