sed または awk を使用して、改行またはスペースまで一致するパターンと前の行を印刷します。

sed または awk を使用して、改行またはスペースまで一致するパターンと前の行を印刷します。

「改行までtmpと前行」を印刷したいです。私はUnixを初めて使用します。

たとえば、次のようになります。

AAA
CBH
VFh

GFD
DFC
VGF
HGD
TMP
JHG

TFD
PI1
98A
TMP
TMP
765
UBS

私が望む出力は次のようになります

GFD
DFC
VGF
HGD
TMP

TFD
PI1
98A
TMP
TMP

答え1

使用awk:

$ awk -v RS='' -v ORS='\n\n' 'match($0,".*TMP") { print substr($0,1,RLENGTH) }' file
GFD
DFC
VGF
HGD
TMP

TFD
PI1
98A
TMP
TMP

これは、1つ以上の空行で区切られた行セットを1つのレコードとして扱います。レコードが正規表現と一致すると、一致する.*TMP部分の後のビットが削除され、レコードの残りの部分が印刷されます。

TMP正規表現を現在のレコードと.*TMP一致させ、その式に一致するビットのみを印刷して、substr()最後の発生以降のビットを削除できます。正規表現はレコードの先頭から最後のレコードまで一致し、関数はTMP変数match()RLENGTH一致長に設定します。

出力レコード区切り文字として二重改行文字を使用するため、出力の末尾に追加の空行が表示されます。


ファイルが次の場合

AAA
CBH
VFh

GFD
DFC
VGF
HGD
tmp/some/path/here
JHG

TFD
PI1
98A
tmp/some/path/here
tmp/some/path/here
765
UBS

...で始まる行に基づいて同じタイプの変換を実行し、コマンドtmpで使用されている正規表現を変更して、末尾のmatch()「-line」までの改行と一致するようにしますtmp

$ awk -v RS='' -v ORS='\n\n' 'match($0,".*tmp[^\n]*") { print substr($0,1,RLENGTH) }' file
GFD
DFC
VGF
HGD
tmp/some/path/here

TFD
PI1
98A
tmp/some/path/here
tmp/some/path/here

awk状況がどうか100%確信できないことを参考にしてください。しなければならない\n括弧式内で解釈されますが、awk私がアクセスできるすべての実装(OpenBSD awk、OpenBSD mawk、およびGNE awk)はこれを改行文字として扱うようです。いいえ2つの別々の文字で\n

答え2

テキストを反転して正規表現から正規表現に正常に印刷し、逆の順序で元の順序を取得します。

 tac < file.txt | sed -n '/TMP/,/^$/p' | tac

答え3

最初のものを一致させることができればTMP。空の場合、RS2つ以上の連続した\n 文字がレコード区切り文字として使用される段落モードになります。

$ # sub is used to remove everything after first occurrence of TMP
$ # return value of sub (0 if no match, 1 if match is found) determines
$ # if record should be printed or not
$ # use \nTMP\n to match only whole line
$ awk -v RS= 'sub(/TMP\n.*/, "TMP\n")' ip.txt
GFD
DFC
VGF
HGD
TMP

TFD
PI1
98A
TMP

最後まで必要ならTMP( GNU awkbecause of gensub) またはperl

$ # use \nTMP\n to match only whole line
$ # same as: perl -00 -ne 'print if s/.*TMP\n\K.*/\n/s' ip.txt
$ awk -v RS= '/TMP/{print gensub(/(.*TMP\n).*/, "\\1", 1)}' ip.txt
GFD
DFC
VGF
HGD
TMP

TFD
PI1
98A
TMP
TMP

答え4

タグ付けにはsedを使用したので、示されているように実行できます。私たちはGNU sedを使用しています。私が理解したところによれば、テキストファイルの各段落でtmp(小文字)で始まる最後の行以降のすべての内容を削除しようとしています。段落は、空白ではなく行で構成される島で、少なくとも1つの空行で次のインスタンスと区別されます。

sed -e '
  /./{H;$!d;}
  x;/\ntmp/!d
  :chop
  /\ntmp[^\n]*$/!s/\n[^\n]*$//
  t chop
' file

段落を蓄積します。境界(空行またはeof)に達すると、短絡チェックを開始します。改行の先頭にtmpが表示されない場合は、このセクションをすぐに削除してください。それ以外の場合は、para 処理を中断して印刷する tmp 行が表示されるまで、para の末尾で行を切り捨て始めます。

GNU awk を使用して tge 段落モードで動作し、入力フィールド区切り文字を改行文字に設定します。最後から始めてフィールドを確認してください。 tmp で始まるフィールドが表示されたら、そのフィールドにパラを絞り込み、印刷して段落を完成させます。

awk -F '\n' -v RS= -v OFS='\n' '
  /(^|\n)tmp/ {
    for(i=NF; i; i--) {
      if ($i ~ /^tmp/) {
        NF=i; NF++; print; break
      }
    }
  }
' file

rindex は、文字列内の部分文字列が最後に始まる場所を示します。したがって、rindex abdを介して最後のtmpの位置を取得し、その位置を使用して次に最も近い改行位置を取得します。

perl -p00e '
  s/.*//s,next unless /^tmp/m;
  s/\z/\n/;
  my $p = 1+rindex($_, "\ntmp");
  my $q = 1+index($_, "\n", $p);
  substr($_, $q) = "\n";
' file

関連情報