Help us understand the problem. What is going on with this article?

awk とシェルとの値の受け渡しについて

More than 1 year has passed since last update.

概要

awk への値の受け渡しの記事はよく見かけるが
awk からシェルへの値の受け渡しの記事が少ないのでまとめてみた。

シェルから awk への値の受け渡し

awk への値の受け渡しは -v オプションを使うと覚えておけば間違いない。

シェルからawkへの値の受け渡し
#!/bin/sh

# -v オプションで値を手入力
echo | awk -v foo=before '{print foo}'
# 実行結果: before

# 後ろには書けない
echo | awk '{print foo}' -v foo=after
# 実行結果: awk: fatal: cannot open file `-v' for reading (No such file or directory)

# -v 無しで渡す方法もあるが、BEGINブロックで値を参照できない
echo | awk 'BEGIN{print foo} {print foo} END{print foo}' foo="Not an option"
# 実行結果:
# 実行結果: Not an option
# 実行結果: Not an option
# -v オプションを使うほうが望ましい
echo | awk -v foo="This is an option" 'BEGIN{print foo} {print foo} END{print foo}'
# 実行結果: This is an option
# 実行結果: This is an option
# 実行結果: This is an option

# 複数指定できる
echo | awk -v foo=first -v bar=second '{print foo, bar}'
# 実行結果: first second

# 変数の値を渡すこともできる
hoge="hello"
fuga="world"
echo | awk -v foo=${hoge} -v bar="$fuga" '{print foo, bar}'
# 実行結果: hello world

# コマンドの実行結果を渡すこともできる
echo | awk -v foo="$( echo 'hello world' | sed -e 's/world/japan/' )" '{ print foo }'
# 実行結果: hello japan

# パイプとの組み合わせ
echo "world" | awk -v foo="hello" '{ bar=foo FS $0; print bar }' | echo -e $(cat)
# 実行結果: hello world

# awk のスクリプト内に直接書く
hoge="hello"
fuga="world"
echo | awk 'BEGIN {print "'"$hoge"'","'"$fuga"'"}'
# 実行結果: hello world

# 文字列のリダイレクト
hoge="hello world"
echo | awk '{print $0}' <<< "$hoge"
# 実行結果: hello world

参照:
awkコマンドへ値を渡す手法のまとめ
awkからシェル変数を参照する
How do I use shell variables in an awk script?

awk からシェルへの値の受け渡し

単一なら $() で代入、
複数なら read で代入が分かりやすい。

awkからシェルへの値の受け渡し
#!/bin/sh

# awk の出力値をバッククォートで囲い、変数に入れる
account_name=`awk -F@ '{print $1}' <<< "account1@domain.com"`
echo ${account_name}
# 実行結果: account1

# 以下も同じく awk の出力値を $() を使って変数に入れる。
account_name=$(awk -F@ '{print $1}' <<< "account2@domain.com")
echo ${account_name}
# 実行結果: account2

# awk の出力を eval で評価する
eval `awk -F@ '{ printf("account_name=\"%s\" ; domain_name=\"%s\"",$1,$2) }' <<< "account3@domain.com"`
echo ${account_name}
echo ${domain_name}
# 実行結果: account3
# 実行結果: domain.com

# 以下も同じ
eval $(awk -F@ '{ printf("account_name=\"%s\" ; domain_name=\"%s\"",$1,$2) }' <<< "account4@domain.com")
echo ${account_name}
echo ${domain_name}
# 実行結果: account4
# 実行結果: domain.com

# set コマンドにて位置パラメータに一旦渡し、それを参照する
set $(awk -F@ '{print $1, $2}' <<< "account5@domain.com")
account_name=$1
domain_name=$2
echo ${account_name}
echo ${domain_name}
# 実行結果: account5
# 実行結果: domain.com

# awk の出力値をreadを使って変数に入れる
read account_name domain_name <<< $( awk -F@ '{print $1, $2}' <<< "account6@domain.com" )
echo ${account_name}
echo ${domain_name}
# 実行結果: account6
# 実行結果: domain.com

# 配列への格納
declare -a array=()
mapfile -t array <<< $( awk -F@ '{print $1, $2}' <<< "account7@domain.com" )
echo "${array[@]}"
# 実行結果: account7 domain.com

以下は <() を使っているので bash でないと機能しない。

bashでないと機能しない
#!/bin/bash

# awk の出力を source で評価する
source <(awk -F@ '{ printf("account_name=\"%s\" ; domain_name=\"%s\"",$1,$2) }' <<< "account8@domain.com")
echo ${account_name}
echo ${domain_name}
# 実行結果: account8
# 実行結果: domain.com

# awk の出力値をreadを使って変数に入れる
read account_name domain_name < <( awk -F@ '{print $1, $2}' <<< "account9@domain.com" )
echo ${account_name}
echo ${domain_name}
# 実行結果: account9
# 実行結果: domain.com

# 配列への格納
declare -a array=()
mapfile -t array < <( awk -F@ '{print $1, $2}' <<< "account10@domain.com" )
echo "${array[@]}"
# 実行結果: account10 domain.com

参照:
シェルのawk内で定義した変数や結果をAwk外で取り扱いたい

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away