「Bash/関数」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(en:Bash/Functionsへの転送ページ)
 
1行目: 1行目:
  +
[[Category:コマンドシェル]]
#redirect[[en:Bash/Functions]]
 
  +
[[en:Bash/Functions]]
  +
[[zh-cn:Bash/Functions]]
  +
[[Bash]] は関数をサポートしています。関数は {{ic|~/.bashrc}} に追加するか、別のファイルに保存して {{ic|~/.bashrc}} から [[ヘルプ:読み方#追加, 作成, 編集 そして source|source]] することで使えます。Bash 関数のサンプルは他にも [https://bbs.archlinux.org/viewtopic.php?id=30155 BBS#30155] にあります。
  +
  +
== エラーコードの表示 ==
  +
  +
{{ic|trap}} を設定して最後に実行したプログラムのゼロ以外のリターンコードを表示するには:
  +
  +
{{hc|~/.bashrc|
  +
EC() {
  +
echo -e '\e[1;33m'code $?'\e[m\n'
  +
}
  +
trap EC ERR
  +
}}
  +
  +
== オンザフライで C ソースをコンパイル・実行 ==
  +
  +
以下の関数は引数で指定した [http://en.wikipedia.org/wiki/C_%28programming_language%29 C] のソースを即座に ({{ic|/tmp/}} ディレクトリの中で) コンパイルして実行します (実行時に引数は付けられません)。プログラムが終了したら、コンパイルしたファイルも削除します。
  +
  +
{{hc|~/.bashrc|<nowiki># Compile and execute a C source on the fly
  +
csource() {
  +
[[ $1 ]] || { echo "Missing operand" >&2; return 1; }
  +
[[ -r $1 ]] || { printf "File %s does not exist or is not readable\n" "$1" >&2; return 1; }
  +
local output_path=${TMPDIR:-/tmp}/${1##*/};
  +
gcc "$1" -o "$output_path" && "$output_path";
  +
rm "$output_path";
  +
return 0;
  +
}</nowiki>}}
  +
  +
== 展開 ==
  +
  +
以下の関数は様々なタイプの圧縮ファイルを展開します。{{ic|extract <file1> <file2> ...}} という構文で使います。
  +
  +
{{hc|~/.bashrc|<nowiki>
  +
extract() {
  +
local c e i
  +
  +
(($#)) || return
  +
  +
for i; do
  +
c=''
  +
e=1
  +
  +
if [[ ! -r $i ]]; then
  +
echo "$0: file is unreadable: \`$i'" >&2
  +
continue
  +
fi
  +
  +
case $i in
  +
*.t@(gz|lz|xz|b@(2|z?(2))|a@(z|r?(.@(Z|bz?(2)|gz|lzma|xz)))))
  +
c=(bsdtar xvf);;
  +
*.7z) c=(7z x);;
  +
*.Z) c=(uncompress);;
  +
*.bz2) c=(bunzip2);;
  +
*.exe) c=(cabextract);;
  +
*.gz) c=(gunzip);;
  +
*.rar) c=(unrar x);;
  +
*.xz) c=(unxz);;
  +
*.zip) c=(unzip);;
  +
*) echo "$0: unrecognized file extension: \`$i'" >&2
  +
continue;;
  +
esac
  +
  +
command "${c[@]}" "$i"
  +
((e = e || $?))
  +
done
  +
return "$e"
  +
}
  +
</nowiki>}}
  +
  +
{{Note|{{ic|extglob}} が有効になっていることを確認してください: {{ic|shopt -s extglob}} を {{ic|~/.bashrc}} に追加します (参照: [http://mywiki.wooledge.org/glob#Options_which_change_globbing_behavior Greg's Wiki:glob#Options which change globbing behavior])。[[Bash#タブ補完|Bash 補完]]を使っている場合、デフォルトで有効になっています。}}
  +
  +
専用のパッケージをインストールする方法もあります。例:
  +
  +
* {{Pkg|unp}} - Perl スクリプトが含まれている公式リポジトリのパッケージ
  +
* {{Pkg|atool}}
  +
* {{AUR|dtrx}}
  +
  +
== cd して ls ==
  +
  +
ディレクトリを変更した後に {{ic|ls}} コマンドで中身を確認するのはよくあります。一度に両方のコマンドを実行することができれば便利でしょう。以下の例では {{ic|cl}} (change list) という名前を付けて同時に実行します。指定されたディレクトリが存在しない場合はエラーメッセージを吐きます。
  +
  +
{{hc|~/.bashrc|<nowiki>
  +
cl() {
  +
local dir="$1"
  +
local dir="${dir:=$HOME}"
  +
if [[ -d "$dir" ]]; then
  +
cd "$dir" >/dev/null; ls
  +
else
  +
echo "bash: cl: $dir: Directory not found"
  +
fi
  +
}
  +
</nowiki>}}
  +
  +
もちろん ''ls'' コマンドは自由に変更できます。例: {{ic|1=ls -hall --color=auto}}。
  +
  +
== シンプルなメモ帳 ==
  +
  +
{{hc|~/.bashrc|<nowiki>
  +
note () {
  +
# if file doesn't exist, create it
  +
if [[ ! -f $HOME/.notes ]]; then
  +
touch "$HOME/.notes"
  +
fi
  +
  +
if ! (($#)); then
  +
# no arguments, print file
  +
cat "$HOME/.notes"
  +
elif [[ "$1" == "-c" ]]; then
  +
# clear file
  +
printf "%s" > "$HOME/.notes"
  +
else
  +
# add all arguments to file
  +
printf "%s\n" "$*" >> "$HOME/.notes"
  +
fi
  +
}
  +
</nowiki>}}
  +
  +
== シンプルなタスクユーティリティ ==
  +
  +
[[#シンプルなメモ帳]] にインスパイアされて作りました。
  +
  +
{{hc|~/.bashrc|<nowiki>
  +
todo() {
  +
if [[ ! -f $HOME/.todo ]]; then
  +
touch "$HOME/.todo"
  +
fi
  +
  +
if ! (($#)); then
  +
cat "$HOME/.todo"
  +
elif [[ "$1" == "-l" ]]; then
  +
nl -b a "$HOME/.todo"
  +
elif [[ "$1" == "-c" ]]; then
  +
> $HOME/.todo
  +
elif [[ "$1" == "-r" ]]; then
  +
nl -b a "$HOME/.todo"
  +
eval printf %.0s- '{1..'"${COLUMNS:-$(tput cols)}"\}; echo
  +
read -p "Type a number to remove: " number
  +
sed -i ${number}d $HOME/.todo "$HOME/.todo"
  +
else
  +
printf "%s\n" "$*" >> "$HOME/.todo"
  +
fi
  +
}
  +
</nowiki>}}
  +
  +
== 電卓 ==
  +
  +
{{hc|~/.bashrc|<nowiki>
  +
calc() {
  +
echo "scale=3;$@" | bc -l
  +
}
  +
</nowiki>}}
  +
  +
== Kingbash ==
  +
  +
Kingbash - メニューを使用する自動補完 ([https://bbs.archlinux.org/viewtopic.php?id=101010 BBS#101010] を参照)。
  +
  +
[[AUR]] から {{AUR|kingbash}}{{Broken package link|{{aur-mirror|kingbash}}}} をインストールして、以下のコードを {{ic|~/.bashrc}} に挿入してください:
  +
  +
{{hc|~/.bashrc|<nowiki>
  +
function kingbash.fn() {
  +
echo -n "KingBash> $READLINE_LINE" #Where "KingBash> " looks best if it resembles your PS1, at least in length.
  +
OUTPUT=$(/usr/bin/kingbash "$(compgen -ab -A function)")
  +
READLINE_POINT=$(echo "$OUTPUT" | tail -n 1)
  +
READLINE_LINE=$(echo "$OUTPUT" | head -n -1)
  +
echo -ne "\r\e[2K"
  +
}
  +
bind -x '"\t":kingbash.fn'
  +
</nowiki>}}
  +
  +
== IP 情報 ==
  +
  +
http://ipinfo.io を使って IP アドレスやホストネームの情報を bash に表示:
  +
  +
{{bc|<nowiki>
  +
ipif() {
  +
if grep -P "(([1-9]\d{0,2})\.){3}(?2)" <<< "$1"; then
  +
curl ipinfo.io/"$1"
  +
else
  +
ipawk=($(host "$1" | awk '/address/ { print $NF }'))
  +
curl ipinfo.io/${ipawk[1]}
  +
fi
  +
echo
  +
}</nowiki>
  +
}}
  +
  +
{{Note|Bash では使える正規表現が制限されています。上記の例では ''grep'' で perl の正規表現を使っています [http://unix.stackexchange.com/questions/84477/forcing-bash-to-use-perl-regex-engine]。}}

2015年11月24日 (火) 18:07時点における版

Bash は関数をサポートしています。関数は ~/.bashrc に追加するか、別のファイルに保存して ~/.bashrc から source することで使えます。Bash 関数のサンプルは他にも BBS#30155 にあります。

エラーコードの表示

trap を設定して最後に実行したプログラムのゼロ以外のリターンコードを表示するには:

~/.bashrc
EC() {
	echo -e '\e[1;33m'code $?'\e[m\n'
}
trap EC ERR

オンザフライで C ソースをコンパイル・実行

以下の関数は引数で指定した C のソースを即座に (/tmp/ ディレクトリの中で) コンパイルして実行します (実行時に引数は付けられません)。プログラムが終了したら、コンパイルしたファイルも削除します。

~/.bashrc
# Compile and execute a C source on the fly
csource() {
	[[ $1 ]]    || { echo "Missing operand" >&2; return 1; }
	[[ -r $1 ]] || { printf "File %s does not exist or is not readable\n" "$1" >&2; return 1; }
	local output_path=${TMPDIR:-/tmp}/${1##*/};
	gcc "$1" -o "$output_path" && "$output_path";
	rm "$output_path";
	return 0;
}

展開

以下の関数は様々なタイプの圧縮ファイルを展開します。extract <file1> <file2> ... という構文で使います。

~/.bashrc
extract() {
    local c e i

    (($#)) || return

    for i; do
        c=''
        e=1

        if [[ ! -r $i ]]; then
            echo "$0: file is unreadable: \`$i'" >&2
            continue
        fi

        case $i in
            *.t@(gz|lz|xz|b@(2|z?(2))|a@(z|r?(.@(Z|bz?(2)|gz|lzma|xz)))))
                   c=(bsdtar xvf);;
            *.7z)  c=(7z x);;
            *.Z)   c=(uncompress);;
            *.bz2) c=(bunzip2);;
            *.exe) c=(cabextract);;
            *.gz)  c=(gunzip);;
            *.rar) c=(unrar x);;
            *.xz)  c=(unxz);;
            *.zip) c=(unzip);;
            *)     echo "$0: unrecognized file extension: \`$i'" >&2
                   continue;;
        esac

        command "${c[@]}" "$i"
        ((e = e || $?))
    done
    return "$e"
}
ノート: extglob が有効になっていることを確認してください: shopt -s extglob~/.bashrc に追加します (参照: Greg's Wiki:glob#Options which change globbing behavior)。Bash 補完を使っている場合、デフォルトで有効になっています。

専用のパッケージをインストールする方法もあります。例:

  • unp - Perl スクリプトが含まれている公式リポジトリのパッケージ
  • atool
  • dtrxAUR

cd して ls

ディレクトリを変更した後に ls コマンドで中身を確認するのはよくあります。一度に両方のコマンドを実行することができれば便利でしょう。以下の例では cl (change list) という名前を付けて同時に実行します。指定されたディレクトリが存在しない場合はエラーメッセージを吐きます。

~/.bashrc
cl() {
	local dir="$1"
	local dir="${dir:=$HOME}"
	if [[ -d "$dir" ]]; then
		cd "$dir" >/dev/null; ls
	else
		echo "bash: cl: $dir: Directory not found"
	fi
}

もちろん ls コマンドは自由に変更できます。例: ls -hall --color=auto

シンプルなメモ帳

~/.bashrc
note () {
    # if file doesn't exist, create it
    if [[ ! -f $HOME/.notes ]]; then
        touch "$HOME/.notes"
    fi

    if ! (($#)); then
        # no arguments, print file
        cat "$HOME/.notes"
    elif [[ "$1" == "-c" ]]; then
        # clear file
        printf "%s" > "$HOME/.notes"
    else
        # add all arguments to file
        printf "%s\n" "$*" >> "$HOME/.notes"
    fi
}

シンプルなタスクユーティリティ

#シンプルなメモ帳 にインスパイアされて作りました。

~/.bashrc
todo() {
    if [[ ! -f $HOME/.todo ]]; then
        touch "$HOME/.todo"
    fi

    if ! (($#)); then
        cat "$HOME/.todo"
    elif [[ "$1" == "-l" ]]; then
        nl -b a "$HOME/.todo"
    elif [[ "$1" == "-c" ]]; then
        > $HOME/.todo
    elif [[ "$1" == "-r" ]]; then
        nl -b a "$HOME/.todo"
        eval printf %.0s- '{1..'"${COLUMNS:-$(tput cols)}"\}; echo
        read -p "Type a number to remove: " number
        sed -i ${number}d $HOME/.todo "$HOME/.todo"
    else
        printf "%s\n" "$*" >> "$HOME/.todo"
    fi
}

電卓

~/.bashrc
calc() {
    echo "scale=3;$@" | bc -l
}

Kingbash

Kingbash - メニューを使用する自動補完 (BBS#101010 を参照)。

AUR から kingbashAUR[リンク切れ: アーカイブ: aur-mirror] をインストールして、以下のコードを ~/.bashrc に挿入してください:

~/.bashrc
function kingbash.fn() {
    echo -n "KingBash> $READLINE_LINE" #Where "KingBash> " looks best if it resembles your PS1, at least in length.
    OUTPUT=$(/usr/bin/kingbash "$(compgen -ab -A function)")
    READLINE_POINT=$(echo "$OUTPUT" | tail -n 1)
    READLINE_LINE=$(echo "$OUTPUT" | head -n -1)
    echo -ne "\r\e[2K"
}
bind -x '"\t":kingbash.fn'

IP 情報

http://ipinfo.io を使って IP アドレスやホストネームの情報を bash に表示:

ipif() { 
    if grep -P "(([1-9]\d{0,2})\.){3}(?2)" <<< "$1"; then
	curl ipinfo.io/"$1"
    else
	ipawk=($(host "$1" | awk '/address/ { print $NF }'))
	curl ipinfo.io/${ipawk[1]}
    fi
    echo
}
ノート: Bash では使える正規表現が制限されています。上記の例では grep で perl の正規表現を使っています [1]