特定の行から/を削除する方法は?

特定の行から/を削除する方法は?

次のファイルがあります

'ABC'|filler|'Y'|'john/1'|'text'
'ABC'|filler|'Y'|'john/1'|'te/xt'
'ABC'|filler|'N'|'mary/2'|'text'
'DEF'|filler|'N'|'jane/3'|'text'

初期のgrep以降、

$ wordY="'Y'|"
$ wordN="'N'|"
$ grep ABC test.txt | grep "$wordY\|$wordN'[[:alpha:]]+/"

戻ってくる

'ABC'|filler|'Y'|'john/1'|'text'
'ABC'|filler|'Y'|'john/1'|'te/xt'    
'ABC'|filler|'N'|'mary/2'|'text'

/今、名前だけを削除して新しい.txtファイルに保存したいと思います。

だから私の理想的な出力は

'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'    -- / should not be removed for 'te/xt'
'ABC'|filler|'N'|'mary2'|'text'

出力を取得するには、コマンドにどのように追加する必要がありますか?

答え1

入力が|フィールド区切り文字として使用される「単純な」CSVファイルであり、埋め込まれた区切り文字または改行付きのフィールドがないと仮定すると、それを使用して変更したい特定のawkフィールドを処理できます。

$ awk -F '|' -v sq="'" 'BEGIN { OFS = FS } $1 == sq "ABC" sq { gsub("/","",$4); print } ' file
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'

入力をフィールドを区切る改行区切りレコードとして読み取り-F '|'ます。インラインスクリプトで一重引用符を処理するのは難しく、コードを読み取ることができないため、変数を一重引用符文字に設定することもできます。awk|awkawksq

コードは、最初のフィールドの値があるレコードを検出し、'ABC'そのレコードの場合(潜在的に)変更されたレコードを出力する前に、4番目のフィールドからスラッシュを削除します。

また、最初のフィールドデータをハードコーディングせずに検出したい文字列全体を変数(ここquery)に渡すこともできます。

$ awk -F '|' -v query="'ABC'" 'BEGIN { OFS = FS } $1 == query { gsub("/","",$4); print } ' file
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'

以下の説明(現在削除済み)に記載されているように、次のことができます。可能変更されたレコードの4列目に実際にスラッシュが含まれている場合にのみ出力されます。これはおそらく単純化する私たちのコマンドは次のとおりです。

awk -F '|' -v query="'ABC'" 'BEGIN { OFS = FS } $1 == query && gsub("/","",$4)' file

このgsub()コマンドは置き換えられた数を返します。つまり、元の 4 番目のフィールドのスラッシュ数を返します。そうでない場合、関数はゼロを返し、その結果ロギングが発生します。いいえ印刷されます。

3番目のフィールドが次のようになりますか?'Y'それとも、次のものを'N'使用できますか?

awk -F '|' -v query="'ABC'" -v yn="^'[YN]'$" '
    BEGIN { OFS = FS }
    $1 == query && $3 ~ yn && gsub("/","",$4)' file

ここでは、3番目のフィールドが変数と一致する必要がある正規表現を渡し、awkそれynを使用して$3 ~ ynテストを実行します。式はまたはと^'[YN]'$一致します。'Y''N'

答え2

使用sed

$ sed -En "\~^('ABC[^YN]*(Y|N)'\|'[[:alpha:]]+)/~s//\1/p" input_file
'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'

答え3

次のことができます。

$ awk 'BEGIN{FS=OFS="|"; q="\047"} 
       ($1==q"ABC"q)&&($3~q"Y|N"q)&&($4~"/") { sub("/","",$4);print }
      ' test.txt

'ABC'|filler|'Y'|'john1'|'text'
'ABC'|filler|'Y'|'john1'|'te/xt'
'ABC'|filler|'N'|'mary2'|'text'

フィールド区切り記号と出力フィールド区切り記号を同じ値()に設定します|。次に、引用符文字を使用して変数を生成しq="047"(これを行うとスクリプトの残りの部分が単純化されます)、次の3つをテストします。

  • 最初のフィールドはとまったく同じです'ABC'
  • 3番目のフィールドは'Y'またはです'N'
  • 4番目のフィールドには実際に/

次に、次のようにします。

  • /4番目のフィールドの最初のフィールドを削除します。
  • 行全体を印刷します。

これは、正規表現を使用してgrep Test ABCに公開したgrepコマンドとは異なります。それがあなたが望むものである場合、または単に$1 == q"ABC"q置き換えてください(これを行うと、入力ライン全体でABCを見つけることができます)。$1 ~ "ABC"~"ABC"

これらの値の1つに対するすべての入力ラインをテストすることも重複しYているようです。Nその場合は、2番目のテストを削除できます。

これは awk コマンドを次のように簡素化します。

awk '($1~/ABC/)&&sub("/","",$4)' FS="|" OFS="|" test.txt

4番目のフィールドのすべての項目を交換する必要がある場合は、/変更機能を使用できます。一部のオペレーティングシステム(現在のオペレーティングシステムを含む)では、subgsub以前のawk実装gsubをサポートしていない可能性があります。

答え4

tr次のコンテンツの場合:

grep ABC test.txt | grep "$wordY|$wordN'[[:alpha:]]+/" | tr -d '/'

trは「翻訳」の略で、特定のセットに表示される文字を削除するか、別のセットの同じ場所にある文字に置き換えることで変更できます。

この-dパラメータは「文字削除」モードを選択します。ここでは、指定されたセット(ここでセットは1文字 "/")の文字が出力に書き換えられる前に入力から削除されます。

詳細についてはを参照してくださいman tr

関連情報