ファイルに表示される最後の単語を置き換える

ファイルに表示される最後の単語を置き換える

シナリオは、シェルスクリプトで最後に表示された単語をコメントアウトしたいということですsed

temp.sh以下があるとしましょう。

Abc 123 Abc
Sdf 2
Abc
Abc
Utyr
Qww

Abc私は最後のインスタンス(行の先頭に発生)を次のように置き換えたいと思います。#Abc 結局のところ、結果は次のようになります。

Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

答え1

ファイルを元に戻すには、最初のファイルをコメントアウトしてからファイルを元に戻します。

$ tac temp.sh | sed '0,/^Abc/{s/^Abc/#&/}' | tac
Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

これは、「行0から始まり、最初の行が一致するまで続行し、その行のみがこの/^Abc/場合()に一致するものにAbc置き換えられることを意味します。ありがとうございます。##Abcこの回答

これにはtacGNUツールとGNU実装が必要ですsed

ソースファイルを変更するには、次のようにします。

tac temp.sh | sed '0,/^Abc/{s/^Abc/#&/}' | tac > temp1.sh &&
  mv temp1.sh temp.sh

またはPerlでは:

$ tac temp.sh | perl -pe 'next if $k; $k++ if s/^Abc/#$&/ ' | tac
Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

ソースファイルを変更するには、次のようにします。

tac temp.sh | perl -pe 'next if $k; $k++ if s/^Abc/#$&/ ' | tac> temp1.sh &&
  mv temp1.sh temp.sh

または使用ステファンの純粋なperlアプローチまたは先行きれいなsed、両方とも-i生ファイルを編集するために使用されます。

答え2

$ sed -e 'H; $!d' -e 'g; s/\n\(.*\n\)\(Abc\)/\1#\2/' file
Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

これにより、ファイル全体が予約済みスペースに読み込まれ、変更されたsed後に変更されたテキストが出力されます。

最初の2つのsed式をH合計し、$!d各行を予約済みスペースに追加してから、次のループにジャンプします(入力の最後の行にない場合)。

このgコマンドは最後の行に対して実行され、予約済みスペースの内容を取得します。その後、置換はその中の最初の改行を削除し(最初の行を空の予約スペースに追加し)、#最後の改行の前にAbc文字を挿入します。

私達は得ることを保証します最後 Abc改行文字以降は.*欲が多いので、できるだけ一致するようになります。

-iファイルを内部で編集できます(sedBSDにsed必要なGNUを使用-i '.bak')。

sed -i'.bak' -e 'H; $!d' -e 'g; s/\n\(.*\n\)\(Abc\)/\1#\2/' file

ed編集者と一緒に:

$ printf '%s\n' '1;?^Abc?;s//#&/' ,p Q | ed -s file
Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

edこれは本質的に単一の編集コマンドを使用して編集を実行します1;?^Abc?;s//#&/。このコマンドは、最初にカーソルをファイルの最初の行(1;Abc文字列が最後の行にある場合は必要です)に移動し、ファイル^Abcで最後に一致する正規表現(?^Abc?)を検索します。見つかったら、#見つかった行の先頭に文字(s//#&/;これは最後に一致した正規表現を再利用し、&後で行の一致部分を挿入するために使用されます)を挿入します#

末尾,pQコマンドはバッファ全体を標準出力として印刷し、無条件に終了します。

答え3

含むawk(パイプを除く):
awk -v str=Abc '
    NR==FNR{if ($0 == str) nr_str=NR; next}
     {print (FNR == nr_str) ? "#"$0 : $0}
' file file
出力
Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

答え4

使用awk:

ファイルを元に戻すには、thenawk関数を使用します。sub()後でファイルを再度反転すると、期待した出力が得られます。

$ tac file |
awk '/^Abc/ && (!found){sub(/^Abc/, "#Abc"); found++}1' |
tac

出力

Abc 123 Abc
Sdf 2
Abc
#Abc
Utyr
Qww

パイプがない場合:

$ awk '
  BEGIN{rec_rep=""; rec_last=""}
       {if (/^Abc/){ 
                   if (rec_rep) print rec_rep;
                                rec_rep = $0;
                                sub(/^Abc/, "#Abc"); 
                                rec_last = $0; 
                                }
          
                   else {       rec_rep = ((rec_rep) ? rec_rep ORS : "") $0;
                                rec_last = ((rec_last) ? rec_last ORS : "") $0 }
  }
  END{print rec_last}' file

関連情報