我的输入有一些字段
这是一个输入示例:
active=1 'oldest active'=0s disabled=0 'function call'=0
我想更换:
|
和 _
输出将是:
active=1|'oldest_active'=0s|disabled=0|'function_call'=0
我尝试了在网上找到的
sed
或perl
不同的解决方案,但没有达到我想要的效果。
$ s="active=1 'oldest active'=0s disabled=0 'function call'=0"
$ echo "$s" | perl -pe "s/'[^']*'(*SKIP)(*F)| /|/g; s/ /_/g"
active=1|'oldest_active'=0s|disabled=0|'function_call'=0
两步更换:
'[^']*'(*SKIP)(*F)
将跳过'
包围的所有图案,并用|
'
内现在留下的空格将替换为_
替代解决方案:
$ echo "$s" | perl -pe "s/'[^']*'/$& =~ s| |_|gr/ge; s/ /|/g"
active=1|'oldest_active'=0s|disabled=0|'function_call'=0
'[^']*'/$& =~ s| |_|gr/ge
使用另一个替换命令替换匹配模式 '[^']*'
中的所有空格。 e
修饰符允许在替换部分使用命令而不是字符串s/ /|/g
延伸阅读:
这可能对你有用(GNU sed):
sed -r ":a;s/^([^']*('[^ ']*')*[^']*'[^' ]*) /\1_/;ta;y/ /|/" file
这首先将引用字符串中的所有空格替换为
_
的空格,然后将剩余的空格转换为 |
的空格。
@anubhava 的解决方案让人想起老式的 Perl 解决方案:
$ echo $s | perl -047 -pe "(\$.%2)?s/ /|/g:s/ /_/g;"
active=1|'oldest_active'=0s|disabled=0|'function_call'=0
用单引号 (047) 分隔行并根据偶数/奇数进行细分。
使用 gnu awk
RS
,您可以使用这个简单的解决方案:
s="active=1 'oldest active'=0s disabled=0 'function call'=0"
awk -v RS="'[^']*'" '{gsub(/ /, "|"); ORS=RT} 1' <<< "$s"
active=1|'oldest active'=0s|disabled=0|'function call'=0
详情:
-v RS="'[^']*'"
它告诉 awk
记录分隔符是每个单引号文本,即 '...'
gsub(/ /, "|")
将剩余空格 (引号外) 替换为 |
ORS=RT
设置输出记录分隔符与 v RS='...'
1
输出每条记录参考: 有效的AWK编程
我们可以在循环内使用正则表达式。
$str = "active=1 'oldest active'=0s disabled=0 'function call'=0";
print "\nBEF: $str\n";
$str =~s#active=1 'oldest active'=0s disabled=0 'function call'=0# my $tmp=$&; $tmp=~s/\'([^\']*)\'/my $tes=$&; $tes=~s{ }{\_}g; ($tes)/ge; $tmp=~s/ /\|/g; ($tmp); #ge;
print "\nAFT: $str\n";
除此之外可能还会有一些捷径。
$ awk -F\' '{OFS=FS; for (i=1;i<=NF;i++) gsub(/ /,(i%2?"|":"_"),$i)}1' file
active=1|'oldest_active'=0s|disabled=0|'function_call'=0