如果该行不使用sed包含另一个字符串,则将文本插入行

时间:2018-06-05 10:41:49

标签: regex bash sed

我在Linux服务器上合并了许多文本文件,但有些文本文件略有不同,我需要统一它们。

例如,某些文件会有

这样的行
id='1244' group='american' name='fred',american

其他文件就像

id='2345' name='frank', english

最后其他人会像

id='7897' group='' name='maria',scottish

我需要做的是,如果组=''或者字符串根本不在字符串中我需要在逗号之前将它添加到逗号之前的文本中,所以在上面的第二个例子中,该行将变为:

id='2345' name='frank' group='english',english

和最后一个将成为

的例子相同
id='7897' name='maria' group='scottish',scottish

这是一个bash脚本。我无法删除该行并添加到文件的末尾,因为它与以下行相关。

我使用了以下内容:

sed -i.bak 's#group=""##' file 

删除组=""字符串,这样行将包含group =' something'或根本不包含它,这是有效的

然后我尝试使用以下内容添加该组:

sed -i.bak '/group/! s#,(.*$)#group="\1",\1#' file

但是会引发错误

sed: -e expression #1, char 38: invalid reference \1 on `s' command's RHS
Ed Morton的

编辑创建单个样本输入文件和预期输出:

示例输入:

id='1244' group='american' name='fred',american
foo
id='2345' name='frank', english
bar
id='7897' group='' name='maria',scottish

预期产出:

id='1244' group='american' name='fred',american
foo
id='2345' name='frank' group='english',english
bar
id='7897' name='maria' group='scottish',scottish

4 个答案:

答案 0 :(得分:1)

类似

sed  '
    /^[^,]*group[^,]*,/ ! {
        s/, *\(.*\)/ group='\''\1'\'', \1/
    }
    /^[^,]*group='\'\''/ {
        s/group='\'\''\([^,]*\), *\(.*\)/group='\''\2'\''\1, \2/
    }
'

答案 1 :(得分:1)

sed -r "
    /group=''/ s///                                   # group is empty, remove it
    /group=/!  s/,[[:blank:]]*(.+)/ group='\\1',\\1/  # group is missing, add it
" file
id='1244' group='american' name='fred',american
foo
id='2345' name='frank' group='english',english
bar
id='7897'  name='maria' group='scottish',scottish

foo和bar行未被触及,因为s ///命令与后跟字符的逗号不匹配。

答案 2 :(得分:0)

此GNU awk可能有所帮助:

awk -v sq="'" '
  BEGIN{RS="[ ,\n]+"; FS="="; found=0}
  $1=="group"{
    if($2==sq sq) 
      {next}
    else
      {found=1}
  }
  NF>1{
    printf "%s=%s ",$1,$2
  }
  NF==1{
    if(!found)
      {printf "group=%s",$1}
    print ","$1
    found=0
  }
' file

该脚本依赖于记录分隔符RS,该分隔符设置为获取所有key='value'对。

如果找不到密钥group或为空,则在到达只有一个字段的记录时会打印出来。

请注意,变量sq包含单引号字符,用于检测空group字段。

答案 3 :(得分:0)

Sed很难看。而且您的数据格式似乎有些不一致。这可能适合你:

$ sed -e "/group='[a-z]/b e" -e "s/group='' *//" -e "s/,\([a-z]*\)$/ group='\1', /" -e ':e' input.txt

为便于阅读而破碎,这是我们正在做的事情:

  • /group='[a-z]/b e - 如果该行包含有效的group,则分支到最后。
  • s/group='' *// - 删除所有空组,
  • s/,\([a-z]*\)$/ group='\1', / - 根据您的规范添加新组
  • :e - 第一个命令的分支标签。
  • 然后默认操作是打印该行。

我真的不喜欢这样操纵数据。它容易出错,您将进一步将这些数据读入准确存储其数据结构的内容,然后根据新结构打印数据。一个更强大的解决方案可能直接与产生或消费这些数据的任何东西联系在一起,并且不会像这样处于中间位置。