1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Shellの基本を学ぶ(4)Input and Output

Posted at

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
1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?