7

この sed の質問の答えを見つけようとしているときに、理解できない奇妙な動作を思いつきました。

というファイルがあるとしましょうdata

$> cat data
foo.png
abCd.png
bar.png
baZ.png

タスクは、行内で sed を使用して、すべての行を大文字の ASCII 文字から小文字に置き換えることです。したがって、出力は次のようになります。

$> cat data
foo.png
abcd.png
bar.png
baz.png

このソリューションは、Mac の sed のように非 gnu sed でも動作するはずです

この埋め込み awk を sed の交換部品にしようとしました:

sed -E 's/[^ ]*[A-Z][^ ]*.png/'$(echo \&|awk '{printf("<%s>[%s]",$0, tolower($0))}')'/' data

奇妙なことに、これはこれを出力します:

foo.png
<abCd.png>[abCd.png]
bar.png
<baZ.png>[baZ.png]

ご覧のとおり、sed は大文字のアルファベットを含む正しい行を選択しています。これは awk にも到達していtolower()ますが、awk の機能は失敗し、入力と同じテキストを生成しています。

シェルの専門家は、この奇妙な動作を説明できますか?

4

7 に答える 7

10

コマンドは、コマンドのサブプロセスとしてではなくawk、コマンドの前に実行されるため、入力としてリテラルのアンパサンドのみを受け取り、その結果として出力されますsedsedawk

<&>[&]

この文字列は、引数として受け取る文字列に埋め込まれます。この文字列から、なぜそのような出力を生成するのsedかがかなり明白になるはずです。sed

イベントのシーケンスは、

  1. シェルはこのコマンドラインを認識します

    sed -E 's/[^ ]*[A-Z][^ ]*.png/'$(echo \&|awk '{printf("<%s>[%s]",$0, tolower($0))}')'/' data
    
  2. コマンド置換 ( にawk変わる)&を処理<&>[&]して、中間コマンド ラインを生成します。

    sed -E 's/[^ ]*[A-Z][^ ]*.png/'<&>[&]'/' data
    
  3. 次に、シェルはsed次のコマンドで実行されますs/[^ ]*[A-Z][^ ]*.png/<&>[&]/

于 2013-05-21T15:10:55.333 に答える
7
sed 'y/ABCDEFGHIJKLMNOPQRSYUVWXYZ/abcdefghijklmnopqrstuvwxyz/'
于 2013-05-21T15:57:00.620 に答える
2

Mac/BSD でこれを直接実行するには、sed特に醜いもの ( ) がないと 99% 確信していないので、解決策が見つからsed -e s/A/a/g -e s/B/b/g ...ない限り、インラインで実行する方法を次に示します。sedawk

awk '{print tolower($0) >FILENAME}' data
于 2013-05-21T15:21:52.530 に答える
2

本当にPerlが使えないのですか?

perl -pi.bak -e 's/([^ ]*[A-Z][^ ]*\.png)/\l\1/' file

小文字を指定する場合はバックスラッシュ エル、最初に一致したグループを繰り返す場合はバックスラッシュ 1 です。

于 2013-05-21T17:55:36.643 に答える
2

プレーンで本当に小文字に変換する必要がある場合sed、それは可能ですが、かなり醜いです:

sed -e s/A/a/g -e s/B/b/g -e s/C/c/g -e s/D/d/g -e s/E/e/g -e s/F/f/g -e s/G/g/g -e s/H/h/g -e s/I/i/g -e s/J/j/g -e s/K/k/g -e s/L/l/g -e s/M/m/g -e s/N/n/g -e s/O/o/g -e s/P/p/g -e s/Q/q/g -e s/R/r/g -e s/S/s/g -e s/T/t/g -e s/U/u/g -e s/V/v/g -e s/W/w/g -e s/X/x/g -e s/Y/y/g -e s/Z/z/g

編集:気にしないでください、@ Bruce Barnettのソリューションの方が優れています

于 2013-05-21T15:51:20.680 に答える