我想替换 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
如果要替换inline,需要-i
在sed后面添加。
答案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"
正如您提到的,出于某种原因您想要一行代码,我认为您不太关心可读性,那么:
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