このコマンドでに置き換えるregex
にはどうすればよいですか?$var
echo "$many_lines" | sed -n '/regex/{g;1!p;};h'
$var
のように見える可能性がありますfs2@auto-17
。
このsed
コマンドは、正規表現の直前の行を出力しますが、正規表現を含む行は出力しません。
これがすべてPerlワンライナーで簡単にできるのであれば、それは私にとっては問題ありません。
美しくはありませんが、これで前の行が$var
欲しかったのです。
echo "$many_lines" | grep -B1 "$var" | grep -v "$var"
Perl正規表現では、変数の内容をのような正規表現に補間できます/$foo/
。ただし、内容はパターンとして解釈されます。のリテラルコンテンツと一致させる場合は$foo
、メタ文字をエスケープする必要があります$safe = quotemeta $foo; /$safe/
。これは/\Q$foo\E/
、通常必要なものに短縮できます。末尾\E
はオプションです。
sed正規表現エンジンに同様の機能があるかどうかはわかりません。
Perlワンライナー:perl -ne'$var = "..."; print $p if /\Q$var/; $p=$_'
変数の拡張を可能にするには、一重引用符の代わりに二重引用符を使用します。
echo $many_lines | sed -n "/$var/"'{g;1!p;};h'
正規表現の前の行を探しているので、1つのライナーを使用すると、それほど些細で美しいものにはなりませんが、これが私が行う方法です(Perlのみを使用):
echo "$many_lines" | perl -nle 'print $. if /\Q$var/' | while read line_no; do
export line_no
echo $many_lines | perl -nle 'print if $. - 1 == $ENV{line_no}'
done
または1行でやりたい場合
echo "$many_lines" | perl -nle 'BEGIN {my $content = ""; } $content .= $_; END { while ($content =~ m#([^\n]+)\n[^\n]+\Q$var#gosm) { print $1 }}'
またはこれは、間違いなく一致する必要があります:
echo "$many_lines" | perl -nle 'BEGIN {my @contents; } push @contents, $_; if ($contents[-1] =~ m#\Q$var#o)') { print $contents[-2] if defined $contents[-2]; }
または、二重引用符をエスケープしたくない場合は、ヒアドキュメントも使用できます。
Perlでは次のようになります。
$heredoc = <<HEREDOC;
here is your text and $var is your parameter
HEREDOC
開始したのと同じ文字列でヒアドキュメントを終了することが重要です。私の例では、新しい行の「HEREDOC」です。