「Bash/関数」の版間の差分
ナビゲーションに移動
検索に移動
(en:Bash/Functionsへの転送ページ) |
(他言語へのリンクを追加) |
||
| (4人の利用者による、間の9版が非表示) | |||
| 1行目: | 1行目: | ||
| + | [[Category:コマンドラインシェル]] |
||
| − | #redirect[[en:Bash/Functions]] |
||
| + | [[en:Bash/Functions]] |
||
| + | [[es:Bash (Español)/Functions]] |
||
| + | [[ru:Bash/Functions]] |
||
| + | [[zh-hans: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 ソースをコンパイル・実行 == |
||
| + | |||
| + | 以下の関数は引数で指定した [https://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 補完]] を使っている場合、デフォルトで有効になっています。}} |
||
| + | |||
| + | これを行うもう 1 つの方法は、特殊なパッケージをインストールすることです。[[アーカイブと圧縮#便利なツール]] を参照してください。 |
||
| + | |||
| + | == 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>}} |
||
| + | |||
| + | == 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 の正規表現を使っています [https://unix.stackexchange.com/questions/84477/forcing-bash-to-use-perl-regex-engine]}} |
||
| + | |||
| + | {{TranslationStatus|Bash/Functions|2024-09-30|740736}} |
||
2024年9月30日 (月) 05:12時点における最新版
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"
}
これを行うもう 1 つの方法は、特殊なパッケージをインストールすることです。アーカイブと圧縮#便利なツール を参照してください。
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
}
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
}