Bash配列に読み込む必要のあるfile.txtがあります。次に、スペース、二重引用符、およびすべてのエントリの最初のカンマを除くすべてを削除する必要があります。これが私がどこまで到達したかです:
$ 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|
これはパラメータ置換を介して可能ですか?
コメント
- テキストを保持する必要がある理由はありますか配列、および'できない理由
awk
またはsed
はデータの処理を行いますか? - @ Jeff-配列をループするとより大きなスクリプトで実装する悪夢私は'作業中です。
- @JonRed私は'何を知りませんあなたがやっているので、'問題に選択肢がない可能性は十分にありますが、一般的に、シェルでそのような複雑な文字列のアクロバットをしていることに気付いたときは、'は、実際のプログラミング言語を使用する必要があることを示す非常に良い兆候です。シェルはプログラミング言語として設計されておらず、1つとして使用することはできますが、'より複雑なものには適していません。 perl、python、またはその他のスクリプト言語への切り替えを検討することを強くお勧めします。
- @terdon It 'おかしいですが、ほぼ正確に言って終わりました。この投稿を読む前に、同僚にも同じことをしました。私は基本的に、これがこのスクリプトの最終バージョンであり、それ以上の要件がある場合はPerlで書き直す必要があると述べました。そうです、私は間違いなく同意します
回答
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
コメント
回答
私が見る限り、する必要はありません。これを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
は、iv id = “0501c55813″のフラグとして、2
とg
の組み合わせをサポートしていません。 >
コマンド)。
コメント
- GNU sedでは、
's/,//2g
を使用できます。カンマを削除するには、 2番目から開始 - そして、最後の2つのs ///コマンドは
s/.*/|ELEMENT|&|/
しかし、それはsedにとってもっと手間がかかるかもしれません。 - @glennjackmanおそらく、しかしそれはかなりきれいに見えます。
- ええ、これはより大きなスクリプトの一部です。配列は、出力だけでなく必要です。したがって、パラメータ置換に興味があります。これで配列をループすることもできますが、実装するのは悪夢です。 Terndonは、sedを使用したループのないソリューションを提供しました。これにより、'は、パラメーターの置換が失敗した場合にフォールバックする可能性があります。 = “fb841fb5b8″>
配列の使用に結び付けられていますが、これが最善の解決策です。
回答
ELEMENT="50,n,e,e,d,2" IFS=, read -r first rest <<<"$ELEMENT" printf "%s,%s\n" "$first" "${rest//,/}"
50,need2
ALLCAPS変数名を使用する習慣から抜け出します。最終的には、PATHなどの重要な「システム」変数と衝突し、コードを破壊します。
コメント
- パラメーターの置換ではありません。しかし、ALLCAPS変数名がBashの悪い習慣であることに気づいていませんでした。あなたは良い点を指摘します、それは大雑把なグーグルが間違いなく確認するものです。私のスタイルを改善してくれてありがとう! 🙂
- '人が
PATH=something; ls $PATH
と書いた後、ls: command not found
エラー。 - すべて大文字で名前が付けられた組み込み変数が100近くあります(このmanページをクリックしてくださいリンク)を見る…
回答
[これは本質的により完全に開発されたものです glennjackmannの回答のバージョン]
最初のコンマを区切り文字として使用して、削除されたキーと値から連想配列を作成します。
declare -A arr while IFS=, read -r k v; do arr["${k//[ \"]}"]="${v//[ ,\"]}"; done < file.txt for k in "${!arr[@]}"; do printf "|ELEMENT|%s,%s|\n" "$k" "${arr[$k]}" done |ELEMENT|20,is| |ELEMENT|10,this| |ELEMENT|50,need2| |ELEMENT|40,I| |ELEMENT|60,see| |ELEMENT|30,all|
回答
配列をループして、中間変数を使用できます。
for((i=0; i < "${#ARRAY[@]}"; i++)) do rest="${ARRAY[i]#*,}" ARRAY[i]="${ARRAY[i]%%,*}","${rest//,/}" done
これにより、最初のコンマの後の部分がrest
に割り当てられます。次に、3つの部分を連結して元に戻します。変数:
- 最初のコンマの前の部分
- コンマ
-
rest
でのすべてのカンマの置換
コメント
- これは私の最初の考えであり、例としては十分に単純ですが、これは配列が大きく、'がすでにループしている、より大きなスクリプトの一部であり、すべてです。これは間違いなく機能しますが、私が取り組んでいる'プロジェクトで実装するのは非常に面倒です。
- 十分に公平です。制限内で答えようとしました(パラメーター拡張のみ)。
RANDOMTEXTTHATWILLNEVERBEINTHEFILE
の代わりに使用します。