Linuxコマンドを使用してファイル内の最後の5つの文字列を置き換えたいと思います。
アドバイスしてください。
例:
入力が期待される出力にababa ababa ababa ababa ababa ababa
置き換えられました。aba
abX
ababa abXba abXba abXba abXba abXba
入力は実行の出力にababa ababa ababa ababa ababa ababa ababa
置き換えられます。aba
12
ababa ababa 12ba 12ba 12ba 12ba 12ba
注:文字列は複数行にまたがるか、ファイルのどこにでも配置できます。しかし、最近5試合だけを交換したいと思います。
ファイルに一致するものが100個ある場合、最後の5つの一致が置き換えられます。
答え1
そしてperl
:
perl -0777 -pse '
$count = () = /\Q$string\E/g;
s{\Q$string\E}{$count-- > $n ? $& : $replacement}ge
' -- -string='whatever
even multiple
lines' -replacement='whatever as well' -n=5 -- file
標準出力に結果を送信するのではなく、場所で編集できる-i
オプションが追加されました。file
-p
ファイルのすべてのレコードに対して渡された式sed
のコードを評価するパターンです。e
-e
-0777
レコード区切り文字を不可能なバイト値に設定します。これは、ファイルの全内容であるレコードが1つだけあることを意味します。-s
-varname=value
変数の値をパラメータとして渡すことができます。/regexp/g
$_ =~ m{regexp}g
は現在のレコード(in)に適用され、正規表現がスカラーコンテキストregexp
で一致し、一致リストがリストコンテキストで一致する場合はtrue / falseを返すグローバルアッチャの略語です。ここで正規表現は次のとおりです。m
$_
\Q$string\E
\Q
\E
引用する$string
so は正規表現演算子を含んでいてもリテラル文字列として扱われます。- を使用すると、空の
() = /regexp/g
変数リストに割り当ててリストコンテキストを強制するため、デフォルトでそのエントリを削除しますが、結果はスカラー割り当てに使用されるため、要素数と一致数が提供されます。正規表現なので、$string
レコードの発生回数(の全内容file
)です。 s{regexp}{replacement}ge
:Perlコード式として解釈されるグローバルに一致する.forを置き換えs
ます。g
regexp
replacement
e
replacement
condition ? iftrue : iffalse
ほとんどの言語で見られる一般的なC三項演算子です。$count--
$count
前の増分を返します。一致するものが含まれているもの< $n
に置き換えると、何も実行せず、に置き換えない限り、何もしません。$&
$replacement
答え2
これはawkとsedを使用する1つの方法です。次のようにして、ファイル内の文字列の発生回数を計算します。
grep -o mystring file1.txt | wc -l
この数が20だとしましょう。次に、最初の20-5 = 15項目をランダムな文字列に置き換えます(例:PWWP)。
awk '{for(i=1;i<=NF;i++){if(c<15&&$i=="mystring"){c++;sub("mystring","PWWP",$i)}}}1' file1.txt > file2.txt
sedを使用して、file2.txtから残りの一致(5項目)をすべて削除します。
sed -i 's/mystring//g' file2.txt
そして、2番目のsed操作で元のファイルを復元します。
sed -i 's/PWWP/mystring/g' file2.txt
mv file2.txt file1.txt