だから私は次の質問に答えたいです。sed + 存在しない場合のみ、文字列の前に単語を追加します。そしてsed - 前の文字が特定の文字ではない場合、文字列の文字を置き換えます。そしてさらに一歩進んでください。
_
に完全に変更したいファイルがありますが、\_
2つの制限があるとしましょう。
_
すでに移転がある場合は何も\
起こらないことを願っています。 (私たちは一度も受けたことがないので\\
心配しないでください)- 私たちはしなければならないただ
_
2つの区切り記号の前に表示される場合は、次のように置き換えます。たとえば、とのstart[
間です]end
。
たとえば、次のようになります。
Pretending_we have \_ some start[text that\_is really_cool]end.
Then \_nothing_ would start[happen_ to\_ that crew_]end
に変換されます
Pretending_we have \_ some start[text that\_is really\_cool]end.
Then \_nothing_ would start[happen\_ to\_ that crew\_]end
メモ:\_
場合によっては、各インスタンスを未使用のインスタンスに置き換えてから、すべてのインスタンスをそのインスタンス_
に置き換え\_
て、最初の変更を元に戻すようにsedを接続したいと思います。しかし、コードに他のどの文字があるのかわからないので、そうしたくはなく、可能であれば自分でやりたいです。
また、vimと端末でこれを行う予定です(vimが動作していることを確認するためにテストとして実行し、次に端末で11個の異なるファイルを処理します)。場合に備えて言及します。
編集する:提起されたいくつかの質問に答えるには:
- perl/sed/vim はすべて、この問題を処理するために許可される方法です。最善のアプローチが何であるかよくわかりません。私はsed / vimの正規表現に慣れているので、これについて言及しました。 (sedとvimを混同して混乱を引き起こしたようです。その点について非常に残念です。私はほとんどの正規表現要件にsedとvim正規表現を使用することに慣れています。 sedとvimで完全に動作するので、彼らは同じ正規表現処理を使用すると仮定しますが、それはおそらく私が作るべき安全な仮定ではないでしょう、そしてそれについて調べます。
- Ubuntuを使用しています。
- 一般に、開始/終了区切り記号は同じ行にあるので、理論的には安全な仮定になることができます(たとえ方法を知っていれば行は重要ではありませんが、将来の人々には見てみることも有益です。
答え1
私はperl
それを使用します:
perl -pe 's{start\[.*?\]end}{$& =~ s{\\?_}{\\_}gr}ge' < your-file
s
すべての(g
)start[...]end
シーケンスを同じシーケンス($&
正規表現が一致するものを含む)に置き換え、オプションで()の前にあるすべての()を置き換えてs
返します。このフラグは、replacement()がコードとして評価されることを示します。r
g
_
?
\
\_
e
$& =~ s{\\?_}{\\_}gr
e
入れ子になっていないとしますstart[...]end
。
start[...]end
sが複数行にまたがる可能性がある場合は、-0777
入力が一度に1行ではなく全体として処理されるように、このオプション(レコード区切り文字を不可能な値に設定)を追加します。
s/pattern/replacement/flags
¹inと同じ方法を使用してくださいsed
。ただし、in ではperl
作成することもできますs{pattern}{replacement}flags
。これはネストと読みやすさに役立ちます。
答え2
GNU sedのみ:
sed -r ':1;s/(start\[.*[^\])(_.*\]end)/\1\\\2/;t1' file
置換を実行する必要がある場合は、-i
このフラグを最後に設定してください。-ri
答え3
これを行うには、awkコマンドを使用できます。角かっこは#のような他の文字で一時的に便利に置き換えることができます。
cat yourfile.txt| tr '[]' '#'
次に、上記の結果を次のコマンドにパイプします。
awk -F# 'OFS=""; {for (i=1;i<=NF; i++) if(i%2==0){ gsub("\\\\","",$i);gsub("_","\\_",$i);$i="["$i"]"} print $0}'
答え4
複数文字と3番目の引数にGNU RS
awkをRT
使用するmatch()
:
$ awk -v RS=']end' '{ORS=RT} match($0,/(.*start\[)(.*)/,a) { gsub(/\\?_/,"\\_",a[2]); $0=a[1] a[2] } 1' file
Pretending_we have \_ some start[text that\_is really\_cool]end.
Then \_nothing_ would start[happen\_ to\_ that crew\_]end