一般化する
a "b" 'c d' $'e\nf'
引用符を尊重し、スペースと改行文字を保持しながら、単一の文字列を別々のパラメータに変換する方法は?
質問
値のリスト(1行に1つずつ)を引用符付きの文字列(で生成)にエクスポートするスクリプトの出力を読み取り、処理しようとしていますprintf %q
。リストの値はスペースで区切られ、引用符で囲むことができ、スペースと改行を含めることができ、数を知ることができません。
例:a "b" 'c d' $'e\nf'
POSIXシェルスクリプトから値を復元し、それをシェル関数の引数として扱う方法を探しています。
必要なソリューション(優先順位の降順):
- POSIXシェルコマンドとコアユーティリティ
xargs
などprintf
eval
- 吹く
- Perlのような成熟したプログラミング言語
シェルスクリプトのスケルトンprocess.sh
:
#!/bin/sh
set -eu
process() {
printf '>%s<\n' "${@}"
}
main() {
value_list="${1}"
# split value list here and set positional parameters
set -- ???
process "${@}"
}
main "${@}"
望む行動
$ process.sh "a \"b\" 'c d' $'e\nf'"
>a<
>b<
>c d<
>e
f<
これまで何が起こりましたか?
printf
私は(含む%q
)、xargs
ループwhile read
、変更IFS
、バイト区切り引数null
、サブシェル呼び出し、heredocsのさまざまな組み合わせを試しました。xargs
逆参照は許可されていますが、空白に対してのみ可能で、改行文字には許可されず、引数なしでのみ許可されます-d
。- ループは
while read
引数を解析できますが、パイプから入力を読み取っている間にシェル関数を呼び出すことはできません。
ベストアンサー1
この回答は以下に基づいています。コメント渡すイルカチョを使用してzsh
。
シェルスクリプトprocess.sh
:
#!/bin/sh
set -eu
export script="$(readlink -f "${0}")"
split() {
zsh -c 'printf "%s\0" "${(Q@)${(z)1}}"' "${script}/split" "${@}"
}
process() {
printf '>%s<\n' "${@}"
}
main() {
value_list="${1}"
split "${value_list}" | xargs -0 sh -c 'init() { . "${script}"; } && init && process "${@}"' "${script}/main"
}
[ "${#}" -eq 0 ] || main "${@}"
特典
- 効果がある
欠点
- パラメータを削除して無限ループを防ぐために、フォームを呼び出す
process()
スクリプトを関数でラップする必要があるのは少し厄介です。xargs
- 必要
zsh