Bash配列でパラメータ置換を使用する

Bash配列でパラメータ置換を使用する

file.txt を Bash 配列として読み取る必要があります。その後、スペース、二重引用符、各項目の最初のカンマを除くすべて。これが私がどれだけ離れてきたかです:

$ cat file.txt
10,this
2 0 , i s
30,"all"
40,I
50,n,e,e,d,2
60",s e,e"

$ cat script.sh
#!/bin/bash
readarray -t ARRAY<$1
ARRAY=( "${ARRAY[@]// /}" )
ARRAY=( "${ARRAY[@]//\"/}" )
for ELEMENT in "${ARRAY[@]}";do
    echo "|ELEMENT|$ELEMENT|"
done

$ ./script.sh file.txt
|ELEMENT|10,this|
|ELEMENT|20,is|
|ELEMENT|30,all|
|ELEMENT|40,I|
|ELEMENT|50,n,e,e,d,2|
|ELEMENT|60,se,e|

これはカンマを除いて素晴らしい動作します。この猫にスキンを適用する方法はいくつかありますが、これはより大きなスクリプトの一部なので、ここに到達するためにパラメータ置換を使用したいと思います。

|ELEMENT|10,this|
|ELEMENT|20,is|
|ELEMENT|30,all|
|ELEMENT|40,I|
|ELEMENT|50,need2|
|ELEMENT|60,see|

パラメータ置換によってこれを達成できますか?

答え1

bash私が知る限り、その出力を生成するために配列として読む必要はありません。

$ sed 's/[ "]//g; s/,/ /; s/,//g; s/ /,/; s/.*/|ELEMENT|&|/' <file
|ELEMENT|10,this|
|ELEMENT|20,is|
|ELEMENT|30,all|
|ELEMENT|40,I|
|ELEMENT|50,need2|
|ELEMENT|60,see|

このsed式はスペースと二重引用符を削除し、最初のカンマをスペースに置き換え(文字列にスペースがない場合)、他のすべてのカンマを削除し、最初のカンマを復元し、追加データを前に追加します。

またはGNUを使用してくださいsed

sed 's/[ "]//g; s/,//2g; s/.*/|ELEMENT|&|/' <file

(標準sedでは、コマンドフラグの組み合わせはサポートされていません。)2gs

答え2

削除する必要があるものを削除します。sed 今後配列としてロードする(変数名も小文字に注意してください。通常、シェルスクリプトでは大文字変数を避けるのが最善です):

#!/bin/bash
readarray -t array< <(sed 's/"//g; s/  *//g; s/,/"/; s/,//g; s/"/,/' "$1")
for element in "${array[@]}";do
    echo "|ELEMENT|$element|"
done

これにより、サンプルファイルに次の出力が生成されます。

$ foo.sh file 
|ELEMENT|10,this|
|ELEMENT|20,is|
|ELEMENT|30,all|
|ELEMENT|40,I|
|ELEMENT|50,need2|
|ELEMENT|60,see|

パラメータ置換を必ず使用する必要がある場合は、以下を試してください。

#!/bin/bash
readarray -t array< "$1"
array=( "${array[@]// /}" )
array=( "${array[@]//\"/}" )
array=( "${array[@]/,/\"}" )
array=( "${array[@]//,/}" )
array=( "${array[@]/\"/,}" )

for element in "${array[@]}"; do
    echo "|ELEMENT|$element|"
done

答え3

ELEMENT='50,n,e,e,d,2'
IFS=, read -r first rest <<<"$ELEMENT"
printf "%s,%s\n" "$first" "${rest//,/}"
50,need2

変数名をすべて大文字にする習慣を捨ててください。最終的には、PATHなどの重要な「システム」変数と競合してコードが破損する可能性があります。

答え4

配列を繰り返し、中間変数を使用できます。

for((i=0; i < "${#ARRAY[@]}"; i++))
do
  rest="${ARRAY[i]#*,}"
  ARRAY[i]="${ARRAY[i]%%,*}","${rest//,/}"
done

これは最初のコンマの後の部分に割り当てられますrest。次に、3つの部分を元の変数に再度リンクします。

  • 最初のカンマの前の部分
  • カンマ
  • rest各カンマをスペースに置き換えます。

関連情報