为什么 sed 输出 -e 表达式 #1, char 55: 前面的正则表达式无效

为什么 sed 输出 -e 表达式 #1, char 55: 前面的正则表达式无效

我正在尝试编写 sed 命令来查找并替换逗号分隔字符串中的 key=value 。

文件中的示例字符串: KEY_1=value_1,KEY_2=value_2,SOMEKEY=lastValue

使用的 sed 命令:

sed -r 's/KEY_2=.*?((?=,)|$)/KEY_2=new_value/' myFile.txt

如果该键存在,请将其及其值替换为新的键=值。大多数值将以逗号“,”结尾,但异常情况是字符串中最后一个 key=value 不会有 ,。

它在 RedHat Linux VM 上给我以下错误消息

sed:-e表达式#1,字符55:前面的正则表达式无效

我相信这是我尝试过的最后一个“/” /g ,这也是可排除的,因为原始字符串中不应重复任何键。

答案1

sed实用程序不支持类似 Perl 的正则表达式。

相反,你可以使用

$ sed 's/KEY_2=[^,]*/KEY_2=new value/' file
KEY_1=value_1,KEY_2=new value,SOMEKEY=lastValue

或者

$ sed 's/\(KEY_2\)=[^,]*/\1=new value/' file
KEY_1=value_1,KEY_2=new value,SOMEKEY=lastValue

或者, with awk (不使用正则表达式,而是使用与键的精确字符串匹配,这样可以防止当您同时拥有KEY_2and时出现混淆SOME_OTHER_KEY_2):

$ awk -F, -v OFS=, '{ for (i = 1; i <= NF; ++i)
                          if (split($i, a, "=") == 2 && a[1] == "KEY_2") {
                              $i = "KEY_2=new value"
                              break
                          } } 1' file
KEY_1=value_1,KEY_2=new value,SOMEKEY=lastValue

答案2

正如评论中提到的,sed不支持 PCRE 风格的正则表达式(另请参阅:为什么我的正则表达式在 X 中有效但在 Y 中无效?)。你可以perl使用

$ s='KEY_1=value_1,KEY_2=value_2,SOMEKEY=lastValue'

$ echo "$s" | perl -pe 's/KEY_2=.*?((?=,)|$)/KEY_2=new_value/'
KEY_1=value_1,KEY_2=new_value,SOMEKEY=lastValue

$ echo "$s" | perl -pe 's/SOMEKEY=.*?((?=,)|$)/SOMEKEY=new_value/'
KEY_1=value_1,KEY_2=value_2,SOMEKEY=new_value

您可以简化正则表达式:

$ # -l needed to prevent deleting the newline character for last field
$ echo "$s" | perl -lpe 's/KEY_2=\K[^,]+/new_value/'
KEY_1=value_1,KEY_2=new_value,SOMEKEY=lastValue

$ # to prevent partial match
$ echo "$s" | perl -lpe 's/(?<![^,])KEY_2=\K[^,]+/new_value/'
KEY_1=value_1,KEY_2=new_value,SOMEKEY=lastValue

perldoc 命令开关有关此处使用的命令行选项的说明

相关内容