どのように交換できますか?窒素ファイルで文字列(またはパターン)が3番目(たとえば3番目)になるようにコマンドを使用しますか sed
?私の言葉は窒素代わりにファイルに最初に表示される窒素1行の2回目の発生または1行の1回目の発生 窒素一致する行。 1行に複数回表示され、発生(一致)は単語の一部になることがあります。
例:
is
ファイル内で3番目に表示されるtoのみが変更されます。us
私の入力ファイルには以下が含まれています。
hai this is linux.
hai this is unix.
hai this is mac.
hai this is unchanged.
予想される出力は次のとおりです。
hai this is linux.
hai thus is unix.
hai this is mac.
hai this is unchanged.
「this」が「th」に置き換えられました。私たちを」2行目。
答え1
完了するために使用する方がはるかに簡単ですperl
。
3番目の発生位置を変更するには、次の手順を実行します。
perl -pe 's{is}{++$n == 3 ? "us" : $&}ge'
3回ごとに変更してください。
perl -pe 's{is}{++$n % 3 ? $& : "us"}ge'
答え2
sed
前の改行文字が別の文字に置き換えられている場合は、それを使用できます。たとえば、次のようになります。
tr '\n' '\000' | sed 's/is/us/3' | tr '\000' '\n'
純粋(GNU)と同じsed
:
sed ':a;N;$!ba;s/\n/\x0/g;s/is/us/3;s/\x0/\n/g'
(sed
恥ずかしい改行の交換https://stackoverflow.com/a/1252191/4488514)
答え3
代替文字列が1行に1回しか表示されない場合は、さまざまなユーティリティを組み合わせることができます。
入力が「input」ファイルにあり、「is」を「us」に置き換えると、次のようになります。
LINENR=$(cat input | grep -n " is " | head -3 | tail -1 | cut -d: -f1)
cat input | sed ${LINENR}' s/ is / us /'
答え4
p='[:punct:]' s='[:space:]'
sed -Ee'1!{/\n/!b' -e\} \
-e's/(\n*)(.*)/ \2 \1/' \
-e"s/is[$p]?[$s]/\n&/g" \
-e"s/([^$s])\n/\1/g;1G" \
-e:c -e"s/\ni(.* )\n{3}/u\1/" \
-e"/\n$/!s/\n//g;/\ni/G" \
-e's//i/;//tc' \
-e's/^ (.*) /\1/;P;$d;N;D'
このビットには、1行から次の行までの発生回数sed
のみが含まれています。 1行にできるだけis
多くのesを確実に処理する必要があり、is
古い行をバッファリングする必要はありません。is
他の単語に属さない各部分に対して改行を予約するだけです。
その結果、ファイル内の3番目のエントリのみが変更され、各行には数が含まれます。したがって、ファイルが次のような場合:
1. is is isis
2. is does
...印刷されます...
1. is is isis
2. us does
まず、各行の先頭と末尾にスペースを挿入して極端なケースを処理します。これにより、単語の境界をより簡単に決定できます。
次に、ゼロまたは1つの句読点文字(後にスペースが続く)の直後に続くすべてのesの前にewlineを挿入して、有効なesを見つけますis
。別のパスを実行し、空白以外の文字に続くすべての改行を削除します。残りのトークンはandと一致しますが、orは一致しません。\n
is
\n
is.
is
this
?is
次に、各トークンを文字列の最後まで収集します。\ni
行の各一致の文字列の\n
末尾にewlineを追加し、それをi
orに置き換えますu
。\n
文字列の末尾に3つの連続したewlineがクラスタ化されている場合はuを使用し、それ以外の場合はiを使用します。私がauを初めて使ったのは最後の時でもありました。代替操作は無限ループを引き起こし続けましたget line, print line, get line, print line,
。
各tryループサイクルが終わると、挿入されたスペースを消去し、パターンスペースに最初に表示される改行文字のみを印刷してから再実行します。
l
ループの先頭に ook コマンドを追加します。たとえば、次のようになります。
l; s/\ni(.* )\n{9}/u\1/...
...この入力を処理するときに実行される操作を確認してください。
hai this is linux.
hai this is unix.
hai this is mac.
hai this is unchanged is.
...それでこれがすることです:
hai this \nis linux. \n$ #behind the scenes
hai this is linux. #actually printed
hai this \nis unix. \n\n$ #it builds the marker string
hai this is unix.
\n\n\n$ #only for lines matching the
\n\n\n$ #pattern - and not otherwise.
hai this \nis mac. \n\n\n$ #here's the match - 3 ises so far in file.
hai this us mac. #printed
hai this is unchanged is. #no look here - this line is never evaled
is
一行でより多くの es を持つ方が合理的かもしれません。
nthword()( p='[:punct:]' s='[:space:]'
sed -e '1!{/\n/!b' -e\} \
-e 's/\(\n*\)\(.*\)/ \2 \1/' \
-e "s/$1[$p]\{0,1\}[$s]/\n&/g" \
-e "s/\([^$s]\)\n/\1/g;1G;:c" \
-e "${dbg+l;}s/\n$1\(.* \)\n\{$3\}/$2\1/" \
-e '/\n$/!s/\n//g;/\n'"$1/G" \
-e "s//$1/;//tc" -e 's/^ \(.*\) /\1/' \
-e 'P;$d;N;D'
)
これは本質的に同じですが、POSIX BREとデフォルトのパラメータ処理で書かれています。
printf 'is is. is? this is%.0s\n' {1..4} | nthword is us 12
...得る...
is is. is? this is
is is. is? this is
is is. is? this us
is is. is? this is
...有効にする場合${dbg}
:
printf 'is is. is? this is%.0s\n' {1..4} |
dbg=1 nthword is us 12
...私たちはそれが繰り返されるのを見ることができます...
\nis \nis. \nis? this \nis \n$
is \nis. \nis? this \nis \n\n$
is is. \nis? this \nis \n\n\n$
is is. is? this \nis \n\n\n\n$
is is. is? this is
\nis \nis. \nis? this \nis \n\n\n\n\n$
is \nis. \nis? this \nis \n\n\n\n\n\n$
is is. \nis? this \nis \n\n\n\n\n\n\n$
is is. is? this \nis \n\n\n\n\n\n\n\n$
is is. is? this is
\nis \nis. \nis? this \nis \n\n\n\n\n\n\n\n\n$
is \nis. \nis? this \nis \n\n\n\n\n\n\n\n\n\n$
is is. \nis? this \nis \n\n\n\n\n\n\n\n\n\n\n$
is is. is? this \nis \n\n\n\n\n\n\n\n\n\n\n\n$
is is. is? this us
is is. is? this is