カンマ区切りのシェル変数をループします


109

以下のようなUnixシェル変数があるとします

variable=abc,def,ghij

forループを使用してすべての値(abcdefおよびghij)を抽出し、各値をプロシージャに渡したいです。

スクリプトは、任意の数のカンマ区切り値をから抽出できるようにする必要があります$variable


繰り返し処理して正確に何をしたいですか?
SMA 2014

1
各フィールド(たとえばabc)を引数としてプロシージャに渡します。
Ramanathan K 2014

回答:


125

次のスクリプトを使用すると、フィールドがいくつあっても、変数がコンマで区切られている限り、変数を動的にトラバースできます。

variable=abc,def,ghij
for i in $(echo $variable | sed "s/,/ /g")
do
    # call your procedure/other scripts here below
    echo "$i"
done

代わりのecho "$i"間に上記の呼び出し、doおよびdoneループの内側に、あなたはあなたのプロシージャを呼び出すことができますproc "$i"


更新:上記のスニペットは、変数の値にスペースが含まれていない場合に機能します。このような要件がある場合は、変更可能なソリューションの1つを使用してIFS、変数を解析してください。


お役に立てれば。


8
これは$variable、空白が含まれている場合は機能しません。たとえば、variable=a b,c,d=>は3(ab | c | d)ではなく4行(a | b | c | d)を出力します
Dan

同様に、** "value **のような新しい見積もりが追加されています。それを削除する正規表現がある場合は更新してください..
gks

136

IFSをいじら
ない外部コマンドを呼び出さない

variable=abc,def,ghij
for i in ${variable//,/ }
do
    # call your procedure/other scripts here below
    echo "$i"
done

bash文字列操作の使用http://www.tldp.org/LDP/abs/html/string-manipulation.html


3
これの良い点は、異なる区切り文字を使用して複数のループをネストできることです。良い提案です!
Brad Parks

5
で混乱を避けるための素晴らしいヒントIFS
Laimoncijus

13
小さな警告-に値のいずれか$iがスペースを含んでいる場合、それらは分割されます(それがスペース区切りではなくコンマ区切りとして渡される理由である可能性があります)
Toby Speight

4
:前の関数はIFSの設定を変更した場合、これはこれまでの仕事変更...それないfor i in ${variable//,/$IFS} do; echo "$i"; done
ヨープ

2
この方法を試すと、「悪い置換」というエラーメッセージが表示されます。
ロストクロシェ2018年

55

別のフィールド区切り記号を設定する場合は、直接forループを使用できます。

IFS=","
for v in $variable
do
   # things with "$v" ...
done

値を配列に格納してから、「Bashで区切り文字で文字列を分割するにどうすればよいですか?」に示すようにループすることもできます。

IFS=, read -ra values <<< "$variable"
for v in "${values[@]}"
do
   # things with "$v"
done

テスト

$ variable="abc,def,ghij"
$ IFS=","
$ for v in $variable
> do
> echo "var is $v"
> done
var is abc
var is def
var is ghij

このソリューションには、カンマ区切りのリストを反復処理し、各エントリに対してコマンドを実行する方法の幅広いアプローチがあります。

2番目のアプローチの例:

$ IFS=, read -ra vals <<< "abc,def,ghij"
$ printf "%s\n" "${vals[@]}"
abc
def
ghij
$ for v in "${vals[@]}"; do echo "$v --"; done
abc --
def --
ghij --

また、stackoverflow.com / questions / 918886 / … も参照してください。
シェルター2014

うん!私もそれについて考えました、それだけがそれからステップに必要だった:a while配列に読み込むためにそしてもう1つは結果をループするために。
fedorqui「SO害をやめる」2014

3
誰かがbinutilsの束をパイプでつなぐのではなく、シェルの使い方を実際に知っているとき、私は幸せになります。
18

IFS以前の状態に戻す必要がありますか?
スタントン2018

1
@fedorquiやった!それがループしたい唯一の変数であり、それによってyamlファイルが読みやすくなりました(1つのLONG環境変数ではなく、行がたくさんある)
GammaGames

5
#/bin/bash   
TESTSTR="abc,def,ghij"

for i in $(echo $TESTSTR | tr ',' '\n')
do
echo $i
done

sedの代わりにtrを使用したいのですが、sedには\ r \ nのような特殊文字に関する問題がある場合があります。

他の解決策は、IFSを特定のセパレータに設定することです


1

これは、エコーを使用しない代替のtrベースのソリューションで、ワンライナーとして表されます。

for v in $(tr ',' '\n' <<< "$var") ; do something_with "$v" ; done

それはエコーなしで整然と感じますが、それは私の個人的な好みにすぎません。


0

これを試してみてください。

#/bin/bash   
testpid="abc,def,ghij" 
count=`echo $testpid | grep -o ',' | wc -l` # this is not a good way
count=`expr $count + 1` 
while [ $count -gt 0 ]  ; do
     echo $testpid | cut -d ',' -f $i
     count=`expr $count - 1 `
done

しかし、変数testpidのフィールド数がわからない場合はどうなりますか?
Ramanathan K 2014

また、上記の変数の各フィールドを引数としてプロシージャに渡す必要があります。そして、変数の長さがゼロになるまでこれを実行したいと思います。(つまり、すべてのフィールドを一度、処理のためのプロシージャに渡す必要があります)
Ramanathan K '30

手順がわかりません。このリンクから、フィールドの数を取得できます。http://stackoverflow.com/questions/8629330/unix-count-of-columns-in-file。その後、forループをwhileループに入れます。あなたはそれを手に入れることができます。
Karthikeyan.RS 2014

これは私が推測するファイルからフィールドを数えるためです。変数のフィールドをカウントする必要がある場合(変数がtestpid = abc、def、ghijであると想定)
Ramanathan K

変数をエコーし​​、出力をawkにパイプします。または、私の最新の回答を参照してください。役に立つかもしれません。
Karthikeyan.RS 2014

0

IFSを使用せず、スペースを維持する別のソリューション:

$ var="a bc,def,ghij"
$ while read line; do echo line="$line"; done < <(echo "$var" | tr ',' '\n')
line=a bc
line=def
line=ghij

これはbashでは正しく機能しますが、zshはスペースを飲み込みます。
lleaff

0

以下は、IFSを変更せず、カスタム正規表現の区切り文字を取り込むことができる純粋なbashソリューションです。

loop_custom_delimited() {
    local list=$1
    local delimiter=$2
    local item
    if [[ $delimiter != ' ' ]]; then
        list=$(echo $list | sed 's/ /'`echo -e "\010"`'/g' | sed -E "s/$delimiter/ /g")
    fi
    for item in $list; do
        item=$(echo $item | sed 's/'`echo -e "\010"`'/ /g')
        echo "$item"
    done
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.