次のデータセットがあります。
\"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
メモ:
- 同じ行に複数のSTART/END
- 他の場所では削除せずにSTARTとENDの間だけを
\
削除したいと思います。"
- 私のファイルには複数の行があります(上記のものと似ています)。
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
時には、物事を違うと考える必要があります。間にあるすべてを削除するのではなく、行の先頭と文字列、行の最後と最後の間に発生したときにのみ保存する方法に関する質問を回す方が簡単です\\"
。START
END
\\"
START
START
END
END
(もちろんこれが直感的に本当ではない場合)。これは、ゼロ個以上の一致がsed
処理される方法によるものです。*
g
ローカルs///
代替コンテキスト。
最初から最初のSTART
ビットは残りのビットの自然な結果でクリアされますが、END
最後から最後までのビットはクリアされません。したがって、START
行の末尾に別のビットを追加する必要があります。追加のコンテンツを取得したら、各項目にewline文字を追加しSTART
ます。次に、音訳コマンドを使用して、すべての文字を同時にewlineに置き換えるか、その逆に置き換えます。ところで、ここでは音域命令が非常に便利であるだけでなく、代替命令よりも効率的です。\n
END
y///
D
\n
y///
s///
この時点で、l
パターン空間は次のように印刷される。
\\"XXX \\ START sapiodj \\\\" aj \\d 2387 EN\nD hddo\\" START bbcc \\\\" EN\nD ssSTART$
ご覧のとおり、\\"
保存する必要があるすべての文字が行の先頭またはD
aと文字列の間にあり、その間にsはありませんSTART
。D
したがって、不要な文字(追加のsを含む)を削除するグローバル置換は、自分で保存する必要があるg
文字も置き換えます。最後に と s を変更して最後の項目を削除するだけです。s///
D
\n
D
START
これにより、フィールドを確実に区別できます。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
許可されます。だから私の答えはそれに基づいています。
START
sと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
に代替適用」と表示されているため、機能しません。START
END