做各种替换,但只在角色之前

  • 本文关键字:角色 替换 regex bash awk sed
  • 更新时间 :
  • 英文 :


我正在做这样的事情:

echo 'foo_bar_baz=foo_bar_baz' | sed -r 's/_([[:alnum:]])/U1/g'

并得到结果:

fooBarBaz=fooBarBaz

有没有办法获得fooBarBaz=foo_bar_baz

我试图这样做,不贪婪:

echo 'foo_bar_baz=foo_bar_baz' | sed -r 's/([^=].*?)_([[:alnum:]])/1U2/g'

但结果是这样的:

foo_bar_baz=foo_barBaz

我需要的是转换自:

foo_bar_baz=foo_bar_baz

自:

fooBarBaz=foo_bar_baz

编辑: 添加更多通用解决方案,该解决方案也适用于 3 个以上的值,然后再=

awk '
BEGIN{
FS=OFS="="
}
{
num=split($1,array,"_")
for(i=2;i<=num;i++){
val=(val?val:"")toupper(substr(array[i],1,1)) substr(array[i],2)
}
$1=array[1] val
val=""
}
1
'  Input_file


这对awk来说应该是一件容易的事。

echo 'foo_bar_baz=foo_bar_baz' | awk '
BEGIN{
FS=OFS="="
}
{
split($1,array,"_")
$1=array[1] toupper(substr(array[2],1,1)) substr(array[2],2) toupper(substr(array[3],1,1)) substr(array[3],2)
}
1'


要简单地删除第一部分使用中的_(这不会使字母大写(:

echo 'foo_bar_baz=foo_bar_baz' | awk 'BEGIN{FS=OFS="="}{gsub(/_/,"",$1)} 1'

您可以使用

s='foo_bar_baz=foo_bar_baz'
sed -E ':a;s/^([^=_]*)_([[:alnum:]])/1U2/g; ta' <<< "$s"
# => fooBarBaz=foo_bar_baz

查看在线sed演示

  • :a- 定义替换成功时要跳转到的a标签
  • s/^([^=_]*)_([[:alnum:]])/1U2/g- 查找
    • ^- 字符串的开头
    • ([^=_]*)- 组 1(替换模式中的1(:除=_以外的任何 0+ 字符
    • _- 下划线
    • ([[:alnum:]])- 组 2(替换模式中的2(:字母数字字符
    • 1U2- 组 1 值,然后是大写的组 2 值
  • ta-t是一个分支命令,使 sed 返回到a标签并重复匹配。

这可能对你有用(GNU sed(:

sed -E 'h;s/_(.)/u1/g;G;s/=.*=/=/' file

复制当前行。删除所有_的字符,并将以下字符大写。附加副本并将=之间的所有内容替换为单个=

另一种选择:

sed -E ':a;s/_(.*=)/u1/;ta' file 

使用 GNU awk 用于第三个 arg 匹配((:

$ echo 'foo_bar_baz=foo_bar_baz' |
awk '{while (match($0,/(.*)_(.)(.*=.*)/,a)) $0 = a[1] toupper(a[2]) a[3]} 1'
fooBarBaz=foo_bar_baz

请注意,上述解决方案不限于任何特定数量的_,也不限于下划线后的任何特定字母:

$ echo 'wee_sleekit_cowrin_timrous_beastie=foo_bar_baz' |
awk '{while (match($0,/(.*)_(.)(.*=.*)/,a)) $0 = a[1] toupper(a[2]) a[3]} 1'
weeSleekitCowrinTimrousBeastie=foo_bar_baz

如果只想删除后跟小写字母的下划线,请将_(.)更改为_([[:lower:]])

最新更新