根据外部或内部单引号以不同方式替换空格
Replace spaces differently depending on outside or inside single quotes
我的输入有一些字段
- 以空格分隔,
- 其他一些用引号括起来,也用空格分隔
这是一个示例输入:
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
处理
延伸阅读:
我们可以在循环中使用正则表达式。
$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";
除此之外可能还有一些捷径。
使用 gnu awk FPAT
,你可以这样做:
s="active=1 'oldest active'=0s disabled=0 'function call'=0"
awk -v OFS="|" -v FPAT="'[^']*'[^[:blank:]]*|[^[:blank:]]+" '{
for (i=1; i<=NF; i++) gsub(/[[:blank:]]/, "_", $i)} 1' <<< "$s"
active=1|'oldest_active'=0s|disabled=0|'function_call'=0
- 在
FPAT
正则表达式中,我们使用交替来创建所有单引号值+非 space 值的字段,即 '[^']*'[^[:blank:]]*
或非白色 space 值,即[^[:blank:]]+
来自输入。
- 使用
gsub
我们只需将所有 space 替换为 _
因为我们只会在所有字段中得到单引号内的 space。
- 最后使用
OFS='|'
我们用 |
分隔输出
这可能对你有用 (GNU sed):
sed -r ":a;s/^([^']*('[^ ']*')*[^']*'[^' ]*) /_/;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
根据even/odd.
用单引号(047)分行
$ 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
我的输入有一些字段
- 以空格分隔,
- 其他一些用引号括起来,也用空格分隔
这是一个示例输入:
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
处理
延伸阅读:
我们可以在循环中使用正则表达式。
$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";
除此之外可能还有一些捷径。
使用 gnu awk FPAT
,你可以这样做:
s="active=1 'oldest active'=0s disabled=0 'function call'=0"
awk -v OFS="|" -v FPAT="'[^']*'[^[:blank:]]*|[^[:blank:]]+" '{
for (i=1; i<=NF; i++) gsub(/[[:blank:]]/, "_", $i)} 1' <<< "$s"
active=1|'oldest_active'=0s|disabled=0|'function_call'=0
- 在
FPAT
正则表达式中,我们使用交替来创建所有单引号值+非 space 值的字段,即'[^']*'[^[:blank:]]*
或非白色 space 值,即[^[:blank:]]+
来自输入。 - 使用
gsub
我们只需将所有 space 替换为_
因为我们只会在所有字段中得到单引号内的 space。 - 最后使用
OFS='|'
我们用|
分隔输出
这可能对你有用 (GNU sed):
sed -r ":a;s/^([^']*('[^ ']*')*[^']*'[^' ]*) /_/;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
根据even/odd.
用单引号(047)分行$ 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