Regex 替换包含制表符的行的一部分

Regex 替换包含制表符的行的一部分,regex,bash,replace,sed,awk,Regex,Bash,Replace,Sed,Awk,如何将包含制表符(\t)的行的一部分替换为sed、awk或任何其他内容 线路 <property name="systemVersionDsvTes" value="xxx"/> 或 \t 应替换为: <property name="systemVersionDsvTes" value="yyy"/> 或 \t 值xxx可以变化,在属性名称之前有一个选项卡,在值之前有四个选项卡。此

如何将包含制表符(\t)的行的一部分替换为sed、awk或任何其他内容

线路

    <property name="systemVersionDsvTes"                value="xxx"/>

\t
应替换为:

    <property name="systemVersionDsvTes"                value="yyy"/>

\t
xxx可以变化,在属性名称之前有一个选项卡,在值之前有四个选项卡。此名称-值对是xml文件中唯一的名称-值对

我尝试了以下方法:

ACTUAL_VERSION="\t<property name=\"systemVersionDsvTes\"\t\t\t\tvalue=\"4.1.9\"/>"
NEW_VERSION="\t<property name=\"systemVersionDsvTes\"\t\t\t\tvalue=\"4.1.10\"/>"
sed -i -e "s/$ACTUAL_VERSION/$NEW_VERSION/g" buildSIM.xml
实际版本=“\t”
新版本=“\t”
sed-i-e“s/$ACTUAL\u VERSION/$NEW\u VERSION/g”buildSIM.xml
这导致了一个错误:sed:-e表达式#1,字符65:命令's'(s//?)的未知选项


这个表达有什么问题?使用GNU sed。

命令的错误消息
未知选项(s///?)
指的是可以在第三个斜杠后添加到替换命令中的“选项”。这些选项包括像
g
这样的字母来替换所有出现的模式,而不仅仅是第一个,或者
i
来忽略字母大小写。它通常暗示模式或替换包含额外的斜杠。要处理模式中的斜杠或替换,也必须对其进行转义:

ACTUAL_VERSION="\t<property name=\"systemVersionDsvTes\"\t\t\t\tvalue=\"4.1.9\"\/>"
NEW_VERSION="\t<property name=\"systemVersionDsvTes\"\t\t\t\tvalue=\"4.1.10\"\/>"

天哪,用awk就行了,别担心这些废话:

$ cat file
        <property name="systemVersionDsvTes"                            value="4.1.9"/>

$ ACTUAL_VERSION='\t<property name="systemVersionDsvTes"\t\t\t\tvalue="4.1.9"/>'

$ NEW_VERSION='\t<property name="systemVersionDsvTes"\t\t\t\tvalue="4.1.10"/>'  

$ awk -v act="$ACTUAL_VERSION" -v new="$NEW_VERSION" '{gsub(act,new)}1' file   
        <property name="systemVersionDsvTes"                            value="4.1.10"/>
$cat文件
$ACTUAL_VERSION='\t'
$NEW\u VERSION='\t'
$awk-v act=“$ACTUAL_VERSION”-v new=“$new_VERSION”{gsub(act,new)}1”文件
实际上,在实际的_版本中,您可能希望使用您采用的任何方法对值中的“.”进行转义,因为它们匹配任何字符而不是文字“.”。或者,在awk中,您可以更改为使用字符串比较,而不是重新比较:

$ awk -v act="$ACTUAL_VERSION" -v new="$NEW_VERSION" 'start=index($0,act) { $0=substr($0,1,start-1) new substr($0,start+length(act)) }1' file   
        <property name="systemVersionDsvTes"                            value="4.1.10"/>
$awk-v act=“$ACTUAL_VERSION”-v new=“$new_VERSION”'开始=索引($0,act){$0=substr($0,1,start-1)新的substr($0,开始+长度(act))}1'文件

sed中没有与之等价的东西。

跳过两个正斜杠修复了错误,然后sed按预期工作:sed-i-e“s/$ACTUAL\u VERSION/$NEW\u VERSION/g”文件感谢您提供了这个非常详细的答案。我刚刚测试了这两种解决方案,它们都很有效。如果我转义了“.”s,awk会向我发送警告,但仍然有效。您没有说您运行了什么代码或警告是什么,所以这是猜测,但您可能尝试了gsub()解决方案,awk可能会告诉您需要两个反斜杠才能转义“.”(例如,“4\\.1\\.9”),因为字符串会被解析两次,所以会被指定为字符串,读取时一次,执行时再次执行。您不需要也不应该转义index()解决方案中的“.”,因为index()处理字符串匹配,而不是REs。只使用一个反斜杠“4\.1\.9”gsub()和index()返回相同的警告或警报,即(从pt br翻译):
“awk:warning:escape sequence'\.”视为正常。
。使用两个反斜杠“4\\.1\\.9”,gsub()将变为“4\.1\.10”,index()工作正常。index()与
4\\.1\\.9
配合使用效果很好。问题是-在给定的上下文中,
4\\.1\\.9
是什么意思?当存储在随后在RE上下文中使用的变量中时(例如,使用
~变量
匹配(…,变量)
),表示5个字符
4。1.9
。当存储在随后在字符串上下文中使用的变量中时(例如,使用
index()
),它表示9个字符
4\\。1 \ \ . 9
。在恒定的重新上下文中使用时(例如,
~/…/
),表示7个字符
4\。1 \ . 9
。所以,这一切都“有效”,但你需要明白你告诉awk要做什么才能得到你想要的。
sed -i -e "s#$ACTUAL_VERSION#$NEW_VERSION#g" buildSIM.xml
$ cat file
        <property name="systemVersionDsvTes"                            value="4.1.9"/>

$ ACTUAL_VERSION='\t<property name="systemVersionDsvTes"\t\t\t\tvalue="4.1.9"/>'

$ NEW_VERSION='\t<property name="systemVersionDsvTes"\t\t\t\tvalue="4.1.10"/>'  

$ awk -v act="$ACTUAL_VERSION" -v new="$NEW_VERSION" '{gsub(act,new)}1' file   
        <property name="systemVersionDsvTes"                            value="4.1.10"/>
$ awk -v act="$ACTUAL_VERSION" -v new="$NEW_VERSION" 'start=index($0,act) { $0=substr($0,1,start-1) new substr($0,start+length(act)) }1' file   
        <property name="systemVersionDsvTes"                            value="4.1.10"/>