スペースを含む区切り文字に基づいて文字列を切り取る方法

スペースを含む区切り文字に基づいて文字列を切り取る方法
variable_list="
 any:any:-a -b -c any
 one:one:-c -b -f -m mul
 mul:one:-c -b -f -m mul
"
for f in `echo $variable_list`
do
  c1=`echo $f | cut -d':' -f1`;
  c2=`echo $f | cut -d':' -f2`;
  c3=`echo $f | cut -d':' -f3-`;
  echo "c1==>$c1 and c2==>$c2 and c3==>$c3";
  #exit 0; ###I made mistake here
done;

予想出力:

c1==>any and c2==>any and c3==>-a -b -c any
c1==>one and c2==>one and c3==>-c -b -f -m mul
c1==>mul and c2==>one and c3==>-c -b -f -m mul

編集1:

私はスクリプトが愚かであることに気づき、exit 0実際にこのようなスクリプトがたくさんあるので、最初の反復では最初の行だけをテストしました。それは必要な方法で動作します。

variable_list入力形式/方式を変更せずに保持して上記の出力を得ることはできますか?

(私はbashを使用しています)

答え1

問題はデータの空白に関連しています。シェルは文字列をすべての空白の単語に分割し、ループはfor単語を繰り返します。

variable_list(配列に置き換えない解決策については、この回答の最後の部分を参照してください。)

代わりに適切な配列を使用してください。

variable_list=(
    "any:any:-a -b -c any"
    "one:one:-c -b -f -m mul"
    "mul:one:-c -b -f -m mul"
)

for var in "${variable_list[@]}"; do
    c1=$( cut -d':' -f1  <<<"$var" )
    c2=$( cut -d':' -f2  <<<"$var" )
    c3=$( cut -d':' -f3- <<<"$var" )
    printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done

配列を使用すると、改行や他の文字を使用して区別することなく、個々の変数のセットに独自の配列項目としてアクセスできます。

コードはまた、「here-strings」を使用して(パイプではなく)bash文字列を送信します。cutecho

またはより効果的に、

variable_list=(
    "any:any:-a -b -c any"
    "one:one:-c -b -f -m mul"
    "mul:one:-c -b -f -m mul"
)

for var in "${variable_list[@]}"; do
    IFS=':' read -r c1 c2 c3 <<<"$var"
    printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done

IFSコロンを設定すると、入力はコロン(スペース、タブ、改行の代わりに)に分割されますreadread

上記の引用はすべて重要です。二重引用符がない場合、シェルはの値と3つの変数に対して単語分割とファイル名の一致を実行しvariable_listますvarc

関連:


あなたが追求するのが特定の出力であるならば、不正行為をするかもしれません。

variable_list=(
    "any:any:-a -b -c any"
    "one:one:-c -b -f -m mul"
    "mul:one:-c -b -f -m mul"
)

( IFS=':'; set -f; printf 'c1==>%s and c2==>%s and c3==>%s\n' ${variable_list[@]} )

これは、設定および()シェルオプションがスクリプトの残りの部分に影響を与えないように、サブシェルprintfで実行されます。ここにコロンを設定すると、シェルが拡張されます。IFS-fnoglobIFS引用しない variable_list配列は3つのグループに分かれており、各グループには3つのパラメータがありますprintfprintf最初の3つのパラメータは対応する書式文字列に従って印刷され、すべてのパラメータが処理されるまで書式は3つのパラメータの次のセットに再利用されます。

これにより、ファイル名のワイルドカード文字がある場合は、引用set -f符のない拡張子がファイル名のグロービングをトリガーするのを防ぐことができます。variable_list


改行で区切られた文字列を使用してください。

variable_list="
any:any:-a -b -c any
one:one:-c -b -f -m mul
mul:one:-c -b -f -m mul"

while IFS= read -r var; do
    IFS=':' read -r c1 c2 c3 <<<"$var"
    printf 'c1==>%s and c2==>%s and c3==>%s\n' "$c1" "$c2" "$c3"
done <<<"$variable_list"

これは、ファイルからのように文字列からデータを読み込みます。

関連:

答え2

awkを使用して出力を取得できます。

echo "$variable_list" | awk -F: '
{
  sub("^ ","")
  for(i=1;i<=NF;i++)
    sub(/^/,"c" i "==>",$i)
}1' OFS=" and "

関連情報