現在実行中のsedに追加すると、なぜ機能しないのですか?

現在実行中のsedに追加すると、なぜ機能しないのですか?

次のテキストファイルがあります。

(empty) 
str
int
int 

s/^/\</gこれを現在のsedに追加すると(make it 's/\&/\</g;s/\</\ /g;s/^/\</g')、これが出力されます。

< ##only this line gets a < 
str
int
int 

ただし、たとえば、新しい行を作成してコマンド全体を入力すると、sed -i '' 's/^/\</g' *.p*次のような結果が出力されます。

< 
<str
<int
<int 

違いは何ですか?

答え1

違いは入力と出力です。最初のケースでは\n改行を挿入しました。しかし、まだ同じパターン空間で作業しているので、パターン^空間の先頭は挿入された改行が含まれていても所定の位置に残ります。これが発生するたびに改行を挿入します<

ただし、2番目の場合はnewを使用し、sed最後のseds出力を入力として読み込みます。したがって、すべての改行は別々の入力行として最初のループカウントと共に注入され、各改行には独自の^パターン空間ヘッダがあります。

echo ..... | 
sed 's/./&\
/g;s/^/sed1/' |
sed 's/^/sed2/'

sed2sed1.
sed2.
sed2.
sed2.
sed2.
sed2

しかし…

sed 's/&/</g;s/</\
/g'

...書くのが簡単かもしれません...

sed 'y/&</\n\n/'

...しかし、それぞれの後に改行を追加して[&<]それぞれを置き換えるには、&<のようにします。

sed 's/[&<]/<\
/g'

...しかし、出力が入力とまったく一致しません...

答え2

sed 'expression;expression' 

同じですか?

sed -e 'expression' -e 'expression'

そのうちの多くの場所でシンプルケース付き

sed -e 'expression' | sed -e 'expression'

あなたの場合(私が知っている限り)すべて&をに変更し<てから、<すべてラップし、最後に行の先頭<に追加しようとしています。

s/\&/\</g;s/\</\
/g;s/^/\</g

与えられた入力に基づいて、このsedスクリプトはBSDを使用して次のことを行いますsed

$ sed -f script.sed file
<
<

<

<

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

$ gsed -f script.sed file
<
<
str
<
int
<
int

なぜこれですか?

  1. まず、&ファイルには何もないので(\以前のものは&さらに削除できます)、最初の式は何もしません。
  2. 2番目の表現は\<単語の境界(開始)と一致します。正直なところ、BSDがなぜこのテキストを削除したのか少し混乱していますsed(これがOpenBSDのバグなのか見てみましょうsed)。したがって、サンプルファイルの各単語の先頭に改行文字が挿入されます。
  3. 3番目の式はまだ同じ(現在変更されている)入力ラインで動作し、ラインの先頭<にaを挿入します。

対照的に、単一の式s/^/\</g\以前<g修飾子が必要でない場合)は、単に<各行の先頭にaを挿入します。


フォローアップ:sedOpenBSD 6.1-stableの実装では、挿入された改行文字で始まる行に文字列を追加することに関するバグが修正されました。パッチが提出されました。

関連情報