既知の2つの文字列間の文字の削除

既知の2つの文字列間の文字の削除

次のデータセットがあります。

\"XXX \ START sapiodj \\" aj \d 2387 END hddo\" START bbcc  \\" END ss

\私の要件:STARTとENDの間にあるすべてのバックスラッシュと二重引用符を削除したいです。"

希望の出力:

\"XXX \ START sapiodj  aj d 2387 END hddo\" START bbcc   END ss

メモ:

  1. 同じ行に複数のSTART/END
  2. 他の場所では削除せずにSTARTとENDの間だけを\削除したいと思います。"
  3. 私のファイルには複数の行があります(上記のものと似ています)。
  4. sedただ使用する必要があります。

次の方法を試しましたが("最初に個別に削除しようとしました)、目的の結果が得られませんでした。

sed '/START/,/END/ s/"//g'

答え1

`ファイルに文字がないとします。下のすべての行を別の文字に変更すると、`その文字は入力に表示されません。

sed -e 's/END/`/g;:X' -e 's/\(START[^`]*\)["\]/\1/g;tX' -e 's/`/END/g'

答え2

実際には難しくありませんsed\nセクションを分離するには、いつでもewlineを使用できます。または\n一時的に区切り文字をewlineに変更できます。そしてループなしでこれを行うことができます。

sed 's/$/START/;s/END/&
/g;  y/D\n/\nD/
     s/\([^D]*START\)*[D\"]*/\1/g
     y/\n/D/;s/.....$//
' <<\IN                                           
\"XXX \ START sapiodj \\" aj \d 2387 END hddo\" START bbcc  \\" END ss
IN

時には、物事を違うと考える必要があります。間にあるすべてを削除するのではなく、行の先頭と文字列、行の最後と最後の間に発生したときにのみ保存する方法に関する質問を回す方が簡単です\\"STARTEND\\"STARTSTARTENDEND(もちろんこれが直感的に本当ではない場合)。これは、ゼロ個以上の一致がsed処理される方法によるものです。*gローカルs///代替コンテキスト。

最初から最初のSTARTビットは残りのビットの自然な結果でクリアされますが、END最後から最後までのビットはクリアされません。したがって、START行の末尾に別のビットを追加する必要があります。追加のコンテンツを取得したら、各項目にewline文字を追加しSTARTます。次に、音訳コマンドを使用して、すべての文字を同時にewlineに置き換えるか、その逆に置き換えます。ところで、ここでは音域命令が非常に便利であるだけでなく、代替命令よりも効率的です。\nENDy///D\ny///s///

この時点で、lパターン空間は次のように印刷される。

\\"XXX \\ START sapiodj \\\\" aj \\d 2387 EN\nD hddo\\" START bbcc  \\\\" EN\nD ssSTART$

ご覧のとおり、\\"保存する必要があるすべての文字が行の先頭またはDaと文字列の間にあり、その間にsはありませんSTARTDしたがって、不要な文字(追加のsを含む)を削除するグローバル置換は、自分で保存する必要があるg文字も置き換えます。最後に と s を変更して最後の項目を削除するだけです。s///D\nDSTART

これにより、フィールドを確実に区別できます。sed 入力に関係なくそして、表示されない文字に依存するのではなく、行に絶対表示されない文字(\nもちろんewline文字)に依存します。

完了したら印刷します。

\"XXX \ START sapiodj  aj d 2387 END hddo\" START bbcc   END ss

答え3

そしてsed

sed 's/:/::/g;s/</:l/g;s/>/:g/g; # escape :, <, >
     s/START/&</g; s/END/>&/g;   # replace START/END with <>
     :1
     s/\(<[^>]*\)[\"]/\1/g;t1
     s/[<>]//g;s/:g/>/g;s/:l/</g;s/::/:/g; # restore <>:'

そしてperl

perl -pe's|START.*?END|$&=~y/\\"//rd|ge'

答え4

あなたはコメントとして指摘するこれもawk許可されます。だから私の答えはそれに基づいています。

STARTsとsがバランスを取っていると仮定し、2つのEND単語のうちの1行を分割すると、すべての偶数フィールドからバックスラッシュと二重引用符を削除する必要があります。そのために:

awk -F 'START|END' '{
                      for(i=2;i<=NF;i+=2){ # For each even-numbered field
                        gsub(/["\\]/,"",$i) # Remove " and \ from it
                        $i="START"$i"END" # Put START and END back around it
                      }
                    }' your_file

これは、あなたの実装に私が保証できない機能がawkあると仮定します。gsub

ちなみに、デフォルトでは「行の一致で始まり終わる行の範囲sedに代替適用」と表示されているため、機能しません。STARTEND

関連情報