Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 仅当使用sed的字符串不存在时,才将该字符串添加到行尾_Regex_String_Bash_Awk_Sed - Fatal编程技术网

Regex 仅当使用sed的字符串不存在时,才将该字符串添加到行尾

Regex 仅当使用sed的字符串不存在时,才将该字符串添加到行尾,regex,string,bash,awk,sed,Regex,String,Bash,Awk,Sed,我试图将一个名为“SPEC1”的字符串添加到以BEGIN开头的行的末尾,但前提是该字符串不存在。某些匹配的行可能已经有字符串,也可能尚未有字符串 我的示例文件如下所示: BEGIN value1 value2 value3 SPEC1 some_other_line1 BEGIN value1 value2 value3 value4 some_other_line2 BEGIN value1 value2 BEGIN value1 value2 value3 SPEC1 some_other

我试图将一个名为“SPEC1”的字符串添加到以BEGIN开头的行的末尾,但前提是该字符串不存在。某些匹配的行可能已经有字符串,也可能尚未有字符串

我的示例文件如下所示:

BEGIN value1 value2 value3 SPEC1
some_other_line1
BEGIN value1 value2 value3 value4
some_other_line2
BEGIN value1 value2
BEGIN value1 value2 value3 SPEC1
some_other_line1
BEGIN value1 value2 value3 value4 SPEC1
some_other_line2
BEGIN value1 value2 SPEC1
sed '/BEGIN/ {
s/ \+SPEC1//g
s|\(.*\)|\1 SPEC1|
}' file
结果应该是这样的:

BEGIN value1 value2 value3 SPEC1
some_other_line1
BEGIN value1 value2 value3 value4
some_other_line2
BEGIN value1 value2
BEGIN value1 value2 value3 SPEC1
some_other_line1
BEGIN value1 value2 value3 value4 SPEC1
some_other_line2
BEGIN value1 value2 SPEC1
sed '/BEGIN/ {
s/ \+SPEC1//g
s|\(.*\)|\1 SPEC1|
}' file
我正在使用sed来尝试实现这一点。我当前的sed解决方案如下:

BEGIN value1 value2 value3 SPEC1
some_other_line1
BEGIN value1 value2 value3 value4
some_other_line2
BEGIN value1 value2
BEGIN value1 value2 value3 SPEC1
some_other_line1
BEGIN value1 value2 value3 value4 SPEC1
some_other_line2
BEGIN value1 value2 SPEC1
sed '/BEGIN/ {
s/ \+SPEC1//g
s|\(.*\)|\1 SPEC1|
}' file
对上述情况的解释:

  • 搜索以“BEGIN”开头的行
  • 查找现有字符串“SPEC1”(前面可能还有一个或多个空格),然后全局删除它以清理文件
  • 捕获整个匹配行(sed-BRE样式),并在行后面附加“SPEC1”
  • 有没有更好的方法通过sed、awk、perl或bash实现这一点

    谢谢

    awk '/^BEGIN/&& !/SPEC1$/{$0=$0 FS "SPEC1"}1' inputfile
    BEGIN value1 value2 value3 SPEC1
    some_other_line1
    BEGIN value1 value2 value3 value4 SPEC1
    some_other_line2
    BEGIN value1 value2 SPEC1
    
    如果希望将
    SPEC1
    作为变量:

    awk -v string="SPEC1"$"" '/^BEGIN/&&  $0 !~ string{$0=$0 FS string}1' input
    

    Awk
    解决方案:

    awk '$1=="BEGIN" && $NF!="SPEC1"{ $(NF+1)="SPEC1" }1' file
    
    $ sed -r '/^BEGIN/s/( SPEC1)?$/ SPEC1/' data
    BEGIN value1 value2 value3 SPEC1
    some_other_line1
    BEGIN value1 value2 value3 value4 SPEC1
    some_other_line2
    BEGIN value1 value2 SPEC1
    
    • $1
      -当前记录的第一个字段
    • $NF
      -当前输入记录中的字段数(指向最后一个字段)
    • $(NF+1)
      -为最后一个字段之后的下一个字段生成值
    输出:

    BEGIN value1 value2 value3 SPEC1
    some_other_line1
    BEGIN value1 value2 value3 value4 SPEC1
    some_other_line2
    BEGIN value1 value2 SPEC1
    

    改进OP中提到的
    sed
    版本

    $ sed '/BEGIN/{/ SPEC1/! s/$/ SPEC1/}' ip.txt
    BEGIN value1 value2 value3 SPEC1
    some_other_line1
    BEGIN value1 value2 value3 value4 SPEC1
    some_other_line2
    BEGIN value1 value2 SPEC1
    
    • /BEGIN/
      如果行包含
      BEGIN
      (如果需要,添加行起始限定符)
      • /SPEC1/如果行不包含
        SPEC1
        (如果需要,添加行尾限定符)
      • s/$/SPEC1/
        SPEC1
        添加到行尾

    另一种可能的
    sed
    解决方案:

    awk '$1=="BEGIN" && $NF!="SPEC1"{ $(NF+1)="SPEC1" }1' file
    
    $ sed -r '/^BEGIN/s/( SPEC1)?$/ SPEC1/' data
    BEGIN value1 value2 value3 SPEC1
    some_other_line1
    BEGIN value1 value2 value3 value4 SPEC1
    some_other_line2
    BEGIN value1 value2 SPEC1
    

    使用
    sed
    ,您无法做得更好,因为不支持惰性量词。请注意,
    s|\(.*)\1 SPEC1|
    's |..*.&SPEC1|
    或甚至
    's |$| SPEC1|
    相比更好看,谢谢你提醒我&。谢谢@sundeep,谢谢你提醒。我删除了我的答案,因为我的答案似乎在网页中显示得不好。@yudongshen选择代码,然后单击
    {}
    编辑按钮或使用
    ctrl+k
    快捷方式。谢谢@Sundeep的清晰解释。我喜欢/SPEC1/!否定位:)第二个脚本不会将
    $
    附加到
    字符串的末尾,如果它附加了
    $
    ,那么添加它时它仍然存在。它也会错误地匹配
    FOOSPEC1
    ,只需在$NF上做一个字符串比较(如果您非常想使用regexp,可以在两侧添加锚)。这是正确的方法。清晰、简单、健壮、高效、便携。。。。