Sed 仅限于每个输入行一部分的字符替换
有一个文件,例如Inventory.conf,其中包含以下行:Sed 仅限于每个输入行一部分的字符替换,sed,substitution,string-substitution,Sed,Substitution,String Substitution,有一个文件,例如Inventory.conf,其中包含以下行: Int/domain—home.dir=/etc/int 我需要在=之前替换/和-,但不能在之后替换。 结果应该是: Int_domain_home_dir=/etc/int 我尝试了几个sed命令,但似乎没有一个适合我的需要。使用GNU sed: echo 'Int/domain—home.dir=/etc/int' | sed 'h;s/[^=]*//;x;s/=.*//;s/[/—.]/_/g;G;s/\n//' 输出:
Int/domain—home.dir=/etc/int
我需要在=
之前替换/
和-
,但不能在之后替换。
结果应该是:
Int_domain_home_dir=/etc/int
我尝试了几个sed
命令,但似乎没有一个适合我的需要。使用GNU sed:
echo 'Int/domain—home.dir=/etc/int' | sed 'h;s/[^=]*//;x;s/=.*//;s/[/—.]/_/g;G;s/\n//'
输出:
Int_domain_home_dir=/etc/int
Int\u domain\u home\u dir=/etc/Int
请参阅:man sed
。我想您也要用GNU-sed替换点。:
echo 'Int/domain—home.dir=/etc/int' | sed 'h;s/[^=]*//;x;s/=.*//;s/[/—.]/_/g;G;s/\n//'
输出:
Int_domain_home_dir=/etc/int
Int\u domain\u home\u dir=/etc/Int
请参阅:
man sed
。我假设您也要替换圆点。如果perl
解决方案没有问题:
$ echo 'Int/domain-home.dir=/etc/int' | perl -pe 's#^[^=]+#$&=~s|[/.-]|_|gr#e'
Int_domain_home_dir=/etc/int
字符串匹配从行的开头到但不包括第一次出现的^[^=]+
=
对匹配的字符串执行另一个替换$&=~s |[/.-]| | gr
- 将所有
或/
或
字符替换为-
修饰符将返回修改后的字符串r
- 将所有
修饰符允许在替换部分使用表达式而不是字符串e
用作分隔符,以避免在字符类#
内转义[/.-]
/
$ echo 'Int/domain-home.dir=/etc/int' | perl -pe 's#^[^=]+#$&=~tr|/.-|_|r#e'
Int_domain_home_dir=/etc/int
请注意,我已经更改了示例输入,使用了
-
而不是-
,如果perl
解决方案没有问题,则OP似乎希望使用-
$ echo 'Int/domain-home.dir=/etc/int' | perl -pe 's#^[^=]+#$&=~s|[/.-]|_|gr#e'
Int_domain_home_dir=/etc/int
字符串匹配从行的开头到但不包括第一次出现的^[^=]+
=
对匹配的字符串执行另一个替换$&=~s |[/.-]| | gr
- 将所有
或/
或
字符替换为-
修饰符将返回修改后的字符串r
- 将所有
修饰符允许在替换部分使用表达式而不是字符串e
用作分隔符,以避免在字符类#
内转义[/.-]
/
$ echo 'Int/domain-home.dir=/etc/int' | perl -pe 's#^[^=]+#$&=~tr|/.-|_|r#e'
Int_domain_home_dir=/etc/int
请注意,我已经更改了示例输入,
-
被使用,而不是-
,这似乎是OP根据评论想要的您要求的sed
解决方案,但是在这种情况下awk
解决方案更简单,性能更好,因为您可以通过=
轻松地将行拆分为两个字段,然后有选择地将gsub()
仅应用于第一个字段,以替换感兴趣的字符:
$ awk -F= '{ gsub("[./-]", "_", $1); print $1 FS $2 }' <<< 'Int/domain-home.dir=/etc/int'
Int_domain_home_dir=/etc/int
perl
也提供了优雅的解决方案:
$ perl -F= -ane '$F[0] =~ tr|-/.|_|; print join("=", @F)' <<<'Int/domain-home.dir=/etc/int'
Int_domain_home_dir=/etc/int
如您所见,
awk
解决方案是目前为止最快的,线路内部循环sed
解决方案的性能最差,大约是12倍。您要求的是sed
解决方案,但是awk解决方案更简单,在这种情况下性能更好,因为您可以通过=
轻松地将行拆分为两个字段,然后有选择地将gsub()
仅应用于第一个字段,以替换感兴趣的字符:
$ awk -F= '{ gsub("[./-]", "_", $1); print $1 FS $2 }' <<< 'Int/domain-home.dir=/etc/int'
Int_domain_home_dir=/etc/int
perl
也提供了优雅的解决方案:
$ perl -F= -ane '$F[0] =~ tr|-/.|_|; print join("=", @F)' <<<'Int/domain-home.dir=/etc/int'
Int_domain_home_dir=/etc/int
如您所见,
awk
解决方案是目前为止最快的解决方案,线路内部循环sed
解决方案的性能预计最差,大约为12倍。sed与t
循环(BRE):
使用
t
循环(BRE)进行Sed:
欢迎来到堆栈溢出!请出示你的问题。你应该包括一个你有问题的代码,然后我们可以尝试帮助解决具体的问题。您还应该阅读。欢迎使用堆栈溢出!请出示你的问题。你应该包括一个你有问题的代码,然后我们可以尝试帮助解决具体的问题。例如,您还应该阅读.tnx。然而,它并没有取代“-”。我制作了一个test.txt,只有一行:sed“h;s/[^=]*/;x;s/=.*/;s/[-./]/\ug;g;s/\n//”test.txt这是-(u a)test=确实是。请忽略第一条评论:-)下面是我的评论:例如tnx。但是,它没有替换“-”请看下面:我只做了一行test.txt:cat test.txt这是/a.test=确实是/is.just-结果:sed“h;s/[^=]*/;x;s/=.*/;s/[-./]/\ug;s/\n/”test.txt这是/u a\u test=确实是/is.just-这就是为什么不替换“-”我不明白:-(@HoneyBee,在你的问题中,你使用了
-
,我认为它与-
tnx不同。但是它没有替换“-”。我只使用了一行test.txt:sed“h;s/[^=]*/;x;s/=.*/;s/[-./]/\ug;g;s/\n/.”test.txt这是-_a_test=确实是/is.just-请忽略第一个注释:-)下面是我的注释:例如tnx。但是它没有替换“-”请看下面:我只用一行做了一个test.txt:cat test.txt这是/a.test=确实是/is.just-结果:sed“h;s/[^=]*/;x;s/=././;s/[-./././-././-/\g;s/\n/.”test.txt this-is_a_test=确实如此。这就是为什么不替换“-”我无法理解:-(@HoneyBee,在你的问题中,你使用了-
,我认为它被称为emdash…它与高级Perl技术的-
++不同,但是,老实说,即使有解释,它也可能很难理解+/$&=~tr | \/.-| | r/e'@mklement0,谢谢..添加了tr
替代答案…我个人发现perl
在大多数情况下都能很好地工作,它结合了sed
、awk
和更多的优点,再加上它的正则表达式h