コマンド置換でパラメータ拡張を使用するには?

コマンド置換でパラメータ拡張を使用するには?
  • 月に名前を付けた12のディレクトリを作成したいと思います。そのため、パイプを使用してlocale月名を取得し、カンマtrで区切り、中括弧で囲んでに渡そうとしましたが、mkdir全体が1つの文字列として扱われます。これを避ける方法はありますか?
16:07: temp ⧲ mkdir {$(locale mon | tr \; ,)}

16:18: temp ⧲ ls -lh
total 4.0K
drwxr-xr-x. 2 john john 4.0K Dec 11 16:18 {January,February,March,April,May,June,July,August,September,October,November,December}

16:18: temp ⧲ 

答え1

として使用入力フィールド区切り記号分割出力locale man

IFS=';'
mkdir -- $(locale mon)

答え2

このように中括弧拡張を使用することはできません。xargs代わりに、次を使用します。

locale mon | tr ';' '\n' | xargs mkdir

答え3

通常、このようなコマンド置換(またはパラメータ拡張)では中括弧拡張を使用しません。

Bash 拡張中括弧拡張は非常に不便であるため、Bash では不可能です。最初; zshではそうではありません。なぜなら、zshは中括弧拡張の前にコマンド置換とパラメータ拡張を拡張しますが、中括弧拡張にはリテラル中括弧とカンマが必要なためです。

ただし、kshを使用すると、カンマと中括弧がどこから来たのか気にしないように見えるため、これを行うことができます。これは試したように動作します。

ksh$ mkdir {$(locale mon | tr \; ,)}

比較する:

 # this brace expands
ksh$ x=abc,def; echo {$x}
abc def

 # increasingly silly, but also expands
ksh$ x="foo{abc" y=",def}"; echo $x$y
fooabc foodef

 # it doesn't work like that in zsh
zsh% x=abc,def; echo {$x}
{abc,def}

 # this works sensibly though, the comma is just part of the data
zsh% x=abc,def y=ghi; echo {$x,$y}xyz
abc,defxyz ghixyz

 # this also makes sense
zsh% a=1 b=4; echo {$a..$b}
1 2 3 4

 # but Bash just fails with it
bash$ a=1 b=4; echo {$a..$b}
{1..4}

しかし、本当にしたい場合は、evalBashでも以下を使用して確実に行うことができます.

eval "mkdir {$(locale mon | tr \; ,)}"

信頼できない入力処理に関する一般的な注意事項はすべて含まれていますが、他の答えの解決策を使用する方が良いでしょう。

答え4

{x,y}はい支柱の拡張(元の70年代のcshに由来)、いいえパラメータ拡張

fishシェルでは、リスト拡張はcshパラメータ拡張のように機能します。

たとえば、

> echo //(string split -- ';' (locale mon))//
//January// //February// //March// //April// //May// //June// //July// //August// //September// //October// //November// //December//

それは次のとおりです。

% echo //{January,February,...}//
//January// //February// //...//

csh(またはcshの機能をコピーするシェル)から。

では、Bourne / cshまたはKornに似たシェルの代わりにコマンドの置き換えがfish行われます。(cmd)`cmd`$(cmd)

この場合、rcシェルでも同様です。

; echo //^``(';
'){locale mon}^//
//January// //February// //March// //April// //May// //June// //July// //August// //September// //October// //November// //December//

rcコマンドはor`cmdで置き換えられ、代わりに区切り文字のリストを指定する形式が`{more complex cmd}あります。ここでは、出力末尾の改行文字が最後の要素に含まれたくないため、改行文字の両方を使用していることがわかります。改行に分割し、各要素を1行に1つずつ出力します。``(seps){cmd}$ifs;locale monfishstring split

fish1以外の要素数を含む2つのリストがリンクされている場合、拡張またはcshスタイルの中括弧の拡張とは異なります。

$ rc -c 'echo `{seq 3}^`{seq 3}'
11 22 33
$ fish -c 'echo (seq 3)(seq 3)'
11 12 13 21 22 23 31 32 33
$ fish -c 'echo (seq 2)(seq 3)'
11 12 13 21 22 23
$ rc -c 'echo `{seq 2}^`{seq 3}'
rc: line 0: bad concatenation

このオプションがオンの場合、zshのパラメータ拡張は同様に機能するrcか、実際にはfishcshスタイルの中括弧拡張と同様に機能します。rcexpandparamそして、この拡張スタイルは構文を使用して拡張ごとに有効にできます$^param

パラメータ拡張時にコマンドの置き換えも可能です。

$ echo //${(s[;])^"$(locale mon)"}//
//January// //February// //March// //April// //May// //June// //July// //August// //September// //October// //November// //December//

ここで、$(cmd)コマンド置換は他のほとんどのシェルと同様に末尾の改行文字を削除します。ここで、s[;]引数拡張フラグは引用された代替分割に依存する;のではなく適用されます$IFS

zsh/langinfozshには、モジュールからローカライズされた月名のリストを取得する機能も組み込まれています。

$ zmodload zsh/langinfo
$ echo //${(v)^langinfo[(I)MON_<1-12>]}//
//January// //February// //March// //April// //May// //June// //July// //August// //September// //October// //November// //December//

1要素に改行文字を含めることは可能ですが、非常に面倒です。

関連情報