改行で区切られた複数の段落の1つのコメントを削除するにはどうすればよいですか?

改行で区切られた複数の段落の1つのコメントを削除するにはどうすればよいですか?

説明:GNU sedを使用してください。

現状 - ~/.screenrc、最後の数行:

# name synthpop
# screen -t script emacs -nw /home/$USER/bin/synthpop

# name thrashmetal
# screen -t script emacs -nw /home/$USER/bin/thrashmetal
# number 1
# split -v
# focus
# chdir "/home/$USER/thrashmetal/src"
# screen -t scr watch nl asdkjlek.html
# number 2
# focus
# split
# focus
# screen -t output watch thrashmetal asdkjlek.html
# number 3
# focus
# split
# focus
# chdir "/home/$USER/thrashmetal/plan"
# screen -t soll watch less soll
# number 4
# focus

# name darkwave
# screen -t script emacs -nw /home/$USER/bin/darkwave

目的:

# name synthpop
# screen -t script emacs -nw /home/$USER/bin/synthpop

name thrashmetal
screen -t script emacs -nw /home/$USER/bin/thrashmetal
number 1
split -v
focus
chdir "/home/$USER/thrashmetal/src"
screen -t scr watch nl asdkjlek.html
number 2
focus
split
focus
screen -t output watch thrashmetal asdkjlek.html
number 3
focus
split
focus
chdir "/home/$USER/thrashmetal/plan"
screen -t soll watch less soll
number 4
focus

# name darkwave
# screen -t script emacs -nw /home/$USER/bin/darkwave

現在の試みはほとんど成功しましたが、次の行が表示されたら停止しません。この行は、コメント記号や英数字のない新しい行です。

sed 's+^# \(name thrashmetal\)+\1+;:a;s+# ++;ta' .screenrc

説明、意図:

  • '一連のやるべきことの始まり

  • s変える

  • +「+」を区切り文字として使用してください。

  • # …「#」で始まる行が見つかるまで1行ずつ見てください。

  • \(後で参照できるようにグループを開始

  • name thrashmetalそして「スラッシュメタル名」で続けてください。

  • \)グループの終わり

  • +\1+行の最初の項目を「#」なしでグループ部分に置き換えます。

  • ;そしてその時点から別のことをしてください...

  • :a「a」というループを作ります。

  • ;s各後続の行ごとに1行ずつ交換してください。

  • +「+」を区切り記号に設定

  • # 行の後に続く内容に関係なく、行に「#」が最初に表示される場合...

  • ++何もありません。効果的に削除してください。

  • ;ta失敗したら、段落の終わりに達すると、スラッシュメタルブロックとダークウェーブブロックを区切る2行が壊れます。、次に「a」の位置に戻ります。

  • '一連のやり方が終わりました。

  • .screenrc現在のディレクトリ(マイホームディレクトリ)にある「.screenrc」ファイルに対して一連の操作を実行します。

標準出力:

# name synthpop
# screen -t script emacs -nw /home/$USER/bin/synthpop

name thrashmetal
screen -t script emacs -nw /home/$USER/bin/thrashmetal
number 1
split -v
focus
chdir "/home/$USER/thrashmetal/src"
screen -t scr watch nl asdkjlek.html
number 2
focus
split
focus
screen -t output watch thrashmetal asdkjlek.html
number 3
focus
split
focus
chdir "/home/$USER/thrashmetal/plan"
screen -t soll watch less soll
number 4
focus

name darkwave
screen -t script emacs -nw /home/$USER/bin/darkwave

この問題を解決するには?スラッシュメタル段落の終わりに達するとすぐにループが止まらず、単に次の段落(darkwave段落)にジャンプして続くようにするには、私が何を間違っているのでしょうか?

私の考えでは、そのループにあるものは何でも間違っていると思います...おそらく「t」かもしれませんが、「T」や「b」も切り捨てられません...

ベストアンサー1

sed '/^# name thrashmetal$/,/^$/ s/^# //' file

#これにより、範囲内の各行から最初と後続の空白文字が削除され、置換が適用されます。

範囲は行一致で始まり^# name thrashmetal$、最初の後続の行一致^$(空行)で終わります。

または次に直接翻訳されますawk

awk '/^# name thrashmetal$/,/^$/ { sub(/^# /, "") }; 1' file

ここで、末尾は、1または{ print $0 }の省略形{ print }として現在の(修正可能な)行が出力されるようにします(テキスト印刷はsedスクリプトに暗黙的に適用されます)。


編集者に興味がある人は、ed次の編集コマンドを使用してこの問題を解決できます。

/^# name thrashmetal$/;.,/^$/ s/^# //

これにより、カーソルが目的の段落の最初の行に移動し、空の行に達するまで、その行とすべての後続の行に代替が適用されます。

私たちは使用できません

/^# name thrashmetal$/,/^$/ s/^# //

...アドレスは現在の行に基づいて計算され、現在の行はエディタの起動時にファイルの末尾にあるためです。ファイルの末尾にあるため、アドレスが/^$/開始アドレスよりも前の行になるため、コマンドの範囲は何の影響もありません。 (最初の空白行は現在の行に基づいて段落の先頭の前にあります。)


独自の方法が修正されました(区切り記号をプラス記号からデフォルト値に変更し、複数の式に分割することで移植性が高くなります)。

sed -e '/^# \(name thrashmetal\)/!b' -e 's//\1/' -e :a -e n -e 's/^# //' -e ta file

最初の置換を実行する代わりに、段落の最初の行の一致によって、残りの編集スクリプトをスキップするかどうかが決まります。bその行が見つからない場合はスキップします。

行が見つかったら、それを修正してラベルを作成しますa。次に現在のバッファを印刷し、その内容を次の行に置き換えますn。ループは以前と同様に続き、# バッファの内容が変更されると部分文字列を削除してラベルにループし直します。

最初の試みの主な問題は次のとおりです。

sed 's+^# \(name thrashmetal\)+\1+;:a;s+# ++;ta' .screenrc

... " a-loop"は無条件であるため、最初の置換が成功したかどうかに関係なく、入力されたすべての行に適用されます(最初の2行はコマンドの影響を受けませんが、コピー/貼り付けエラーのようです)。 。ループは次の行も読みませんので、単に実行されます。一度1行あたり(# 1行に複数の部分文字列が見つからない限り)

私の修正は、最初の交換をテストと交換に分割し、交換がa失敗するまで「-loop」が入力の次の行を読み取ることを確認することでした。また、どの行でも複数の文字列や埋め込み(内部)文字列を変更せずに、行の先頭の# 最初の文字列のみを置き換えました。

おすすめ記事