sed を使用したファイルの一部の置換

sed を使用したファイルの一部の置換

xorgファイルの一部を置き換えたいです。 sedを使用してこれを実行できますか?

元のセクション、つまり「Screenセクション」と「EndSection」の間のすべての項目を置き換えます。

Section "Screen"
    Identifier     "Screen0"
    Device         "Device0"
    Monitor        "Monitor0"
    DefaultDepth    24
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

...完全に新しい内容(複数行)に置き換えられました。例えば

Section "Screen"
    SomeSpecs   "somevalue"
    SomeOptions "somevalues"
EndSection

答え1

sed '/Section "Screen"/,/EndSection/s/\(Identifier.*\)Screen0/\1somethingelse/' xorg-file

インラインを交換するには、-isedの後に追加する必要があります。

答え2

行うことができますがsed(実装に応じてやや簡単ですsed)、perl次のものを使用する方が適切です。

file=xorg.conf
screen_to_replace=Screen0
new_section='    Identifier "somethingelse"
    Device ...
'

perl -0777 -spi -e '
  s{^\h*Section\h+"Screen"\h*\n\K.*?(?=^\h*EndSection\h*$)}{
    my $section = $&;
    if ($section =~ /^\h*Identifier\h+"\Q$screen_to_replace\E"\h*$/m) {
      $new_section;
    } else {
      $section;
    }
  }smeg' -- -screen_to_replace="$screen_to_replace" \
            -new_section="$new_section" \
         -- "$file"

または-MEnglish埋め込み文書についてコメントを残してください。

file=xorg.conf
screen_to_replace=Screen0
new_section='    Identifier "somethingelse"
    Device ...
'

perl -MEnglish -0777 -spi -e '
  s{
     ^             # beginning of a line
     \h*           # any amount of horizontal spacing
     Section       # literally
     \h+           # at least one horizontal space
     "Screen"      # literally
     \h*        
     \n            # a line delimiter
     \K            # Keep only what follows from what is matched
     .*?           # anything as little as possibly up until
     (?=           # looking ahead for:
       ^           # beginning of a line
       \h*         # any amount of horizontal spacing
       EndSection  # literally
       \h*         # any amount of horizontal spacing
       $           # the end of a line
     )
  }{
    my $section = $MATCH;
    if ($section =~ m{
      ^           # beginning of a line
      \h*         # any amount of horizontal spacing
      Identifier  # literally
      \h+         # at least one horizontal space
      "\Q$screen_to_replace\E" # "the_old_id", \Q...\E for it to
                               # be taken literally even if it contains
                               # regexp operators.
      \h*         # any amount of horizontal spacing
      $           # the end of a line
    }mx)
    {
      $new_section;
    } else {
      $section;
    }
  }sxmeg' -- -screen_to_replace="$screen_to_replace" \
             -new_section="$new_section" \
          -- "$file"

言及したように、何らかの理由で1行のコードが必要ですが、読みやすさにはあまり気にしないようです。

perl -0777pi -e's{^\h*Section\h+"Screen"\h*\n\K.*?(?=^\h*EndSection\h*$)}{($s=$&)=~/^\h*Identifier\h+"Screen0"\h*$/m?qq(    Identifier "somethingelse"\n    Device ...\n):$s}smeg' xorg.conf

ここにあるすべてのパラメータはハードコードされています。

答え3

まず、方法を見てみましょう。sed 行を選択

# print ('p') lines between line that contain 'Section' and line that contain 'EndSection'
sed -n '/Section/,/EndSection/ p' xorg.conf
# to same + line starts ('^') with these text
sed -n '/^Section/,/^EndSection/ p' xorg.conf
# to same + 'Section' line must contain 'Screen'
sed -n '/^Section.*Screen/,/^EndSection/ p' xorg.conf

「選択行」を定義する

l1='^Section.*Screen'; l2='^EndSection'
# to same as last command (only for test)
sed -n "/$l1/,/$l2/ p" xorg.conf   # be careful, now use " (double quotes)

最後に、いくつかの置換を実行します(sed「言語」置換でs)。これから私たちはいつも平和$l1です$l2

# replace 'Identifier' by 'BLA1'
sed "/$l1/,/$l2/ s/Identifier/BLA1/" xorg.conf
# replace whole line with 'Identifier' by 'BLA2'
sed "/$l1/,/$l2/ s/Identifier.*/BLA2/" xorg.conf
# and finally what do you want
sed "/$l1/,/$l2/ s/Identifier.*/Identifier \"somethingelse\"/" xorg.conf

関連情報