grep、awk、またはsedを使用して文字列リテラルまで行の部分文字列を取得するには?

grep、awk、またはsedを使用して文字列リテラルまで行の部分文字列を取得するには?

テキストファイルを処理しようとしていて、特定の文字列リテラルが行の末尾に表示された場合は省略します。たとえば、

源泉:

ABC 123
DEF, characters I don't want
GHI, these characters are ok

希望の出力:

ABC 123
DEF
GHI, these characters are ok

これにより、grep -v ', characters I don't want$'行全体が無視されます。

部分文字列がawk必要なので、単純な列を作成することはできません。, these characters are ok

cut区切り文字は複数の文字()でなければならないため、区切り文字を使用して分割することはできません, characters I don't want

Pythonでは非常に簡単です。たとえば、次のようになります。string.split(", characters I don't want", 1)[0]

(余談として、このような複雑な状況では、Pythonがより読みやすく、メンテナンスが容易なときにgrep、awk、またはsedを使用するユースケースが実際にPythonより優れているかどうか疑問に思います。)

ベストアンサー1

ここで最も明白なのは、次のことですsed

<source sed "s/, characters I don't want\$//"

シェルでエスケープされた行の末尾で文字列を見つけたら、sその文字列を置き換えます(後でシェルに何かが表示される場合に備えて、将来の証拠として)。$\$$/

その文字列の後の項目(存在する場合)を削除するには、に置き換えます。\$ただし、ユーザーロケールで有効なテキストではない場合でも、最後まですべての項目が一致するように.*Cのロケールを変更する必要があります。.*

<source LC_ALL=C sed "s/, characters I don't want.*//"

GNUgrepまたは互換バージョンの場合、Perl と同様の正規表現サポートでビルドすると、次のようになります。

<source LC_ALL=C grep -Po "^.*?(?=(, characters I don't want)?\$)"

または、その文字列の後のすべての内容を削除します(存在する場合)。

<source LC_ALL=C grep -Po "^.*?(?=, characters I don't want|\$)"

またはpcregrep(Perlと同様の正規表現サポートがGNUで有効になっている場合、grepこれは実際にサンプルアプリケーションとして提供されますが、pcregrepGNU以上の機能を持つlibpcreを介して行われますgrep):

<source pcregrep -o1 "^(.*?)(, characters I don't want)?\$"

または、その文字列の後のすべての内容を削除します(存在する場合)。

<source pcregrep -o1 "^(.*?)(, characters I don't want|\$)"

削除するテキストに/正規表現演算子(意味のない改行、コマンド引数、または環境変数に渡すことができるNUL文字を除く)を含めることができ、シェル変数に格納されている場合は、次のようにします。いいえこれにより、sed "s/$string\$//"コマンド注入の脆弱性が発生する可能性があります。

Perl-grepの場合は、次のものを使用できます。

string='/.*\^$'
<source LC_ALL=C grep -Po "^.*?(?=(\Q$string)?\$)"
<source pcregrep -o1 "^(.*?)(\Q$string\E)?\$"

または、その文字列の後のすべての内容を削除します(存在する場合)。

<source LC_ALL=C grep -Po "^.*?(?=\Q$string|\$)"
<source pcregrep -o1 "^(.*?)(\Q$string\E|\$)"

これは深刻な結果をもたらさなくても、$string孤立したsの窒息を引き起こします。\Esed

あるいは、任意の文字列を渡すためのメカニズムを使用して、オプションのあるモードでperl直接使用することもできます(ここではおおよそのオプションを渡すために使用されますが、直接使用することもできます(Pythonに対応)。または環境変数(連想配列にマップされます) )。文字列は正規表現で引用できます(ここではinは問題ではありません):sed-p-s@ARGVsys.argv%ENV\Q\E$string

<source perl -spe 's/\Q$string\E$//' -- -string="$string"

または、その文字列の後のすべての内容を削除します(存在する場合)。

<source perl -spe 's/\Q$string\E.*$//' -- -string="$string"

perlデフォルトでは、入力はユーザーのロケール文字セットでエンコードされず、バイトとして扱われるため、ここでロケールを変更する必要はありません。

対照的に、行区切り文字はパターン空間(sed基本的$_に機能する場所perl)に含まれており、対応する正規表現演算子はトピックの終わりまたはトピックの終わりの行区切り文字の前に一致するので処理できます。区切られた行と無制限の行。s///$

おすすめ記事