在bash / shell中添加关键字后的文本

时间:2015-03-25 11:41:37

标签: linux bash shell awk

我正在从MSoft迁移PTR记录,我正在调整zonefiles以满足我的需求。我已准备好区域文件,因此它们如下所示:

snapo@jump:~/mike/10$ cat 21.128

102                     [AGE:3630582]   1200    PTR     host1.domain.company.local.                      
69                      [AGE:3630774]   1200    PTR     host2.domain.compan2.local.                    
                        [AGE:3630762]   1200    PTR     host2.domain.company.local.                          
80                      [AGE:3630774]   1200    PTR     hostXX.domain.company.local.  

所以我将文件名作为变量x,我希望用awk实现文本文件的输出(因为我不认为bash中有另一种方式)。请不要php / python / perl答案,因为脚本需要在不同的系统上运行,并且应该安装的唯一语言是bash。 因为这是从多个PTR区域到一个区域的合并,所以我必须编辑区域文件,如下所示:

102.21.128                        [AGE:3630582]   1200    PTR     host1.domain.company.local.                      
69.21.128                         [AGE:3630774]   1200    PTR     host2.domain.compan2.local.                    
21.128                            [AGE:3630762]   1200    PTR     host2.domain.company.local.                          
80.21.128                         [AGE:3630774]   1200    PTR     hostXX.domain.company.local.  

第一行中没有数字可能是“空”,那么它应该在前面没有点的情况下添加它。你有一个awk样品或任何其他样品(切,grep,头,尾,sed)? 命令应替换现有文件中的字符串或输出文件> editedtextfile.txt中的管道或类似字符。

2 个答案:

答案 0 :(得分:3)

使用sed:

 sed 's/^[^[:space:]]\+/&.21.128/' filename

将输入视为纯文本具有保持格式完整的优点。

对于编辑过的问题,可以将其扩展为

sed 's/^[^[:space:]]\+/&.21.128/; s/^[[:space:]]/21.128&/' filename

附录:如果您不想在代码中重复插入的数据,那么

sed 's/^[^[:space:]]*/&\n21.128/; s/^\n//; s/\n/./' filename

是另一种使用更多技巧的方法:它在新数据之前插入标记,如果之前没有任何内容则删除标记,否则用点替换它。

附录2:使用带有sed代码的shell变量有点棘手且有潜在危险(因为代码注入)。如果变量来自可靠的源并且已知不包含任何元字符,则可以编写

sed "s/^[^[:space:]]*/&\n$variable/; s/^\n//; s/\n/./" filename

正如@triplee在评论中指出的那样。如果$variable包含斜杠但没有其他元字符且已知某个字符不包含该字符,则可以为s命令使用不同的分隔符:

sed "s@^[^[:space:]]*@&\n$variable@; s/^\n//; s/\n/./" filename

(如果知道$variable不包含字符@)。

如果不是这种情况,则需要更深层次的魔法。例如,如果已知$variable是一行(我怀疑是这种情况,因为否则转换没有意义),那么就可以编写

(echo "$variable"; cat filename) | sed '1 { h; d; }; s/^[^[:space:]]*/&\n/; G; s/\(.*\n\)\(.*\)\n\(.*\)/\1\3\2/; s/^\n//; s/\n/./'

这将变量作为输入的第一行提供给sed,然后按如下方式工作:

1 { h; d; }                        # first line: hold, don't print
s/^[^[:space:]]*/&\n/              # after that: Insert marker as before
G                                  # fetch variable from the hold buffer
s/\(.*\n\)\(.*\)\n\(.*\)/\1\3\2/   # move it to the right place
s/^\n//                            # rest as before.
s/\n/./

但是,此时您可能需要考虑使用awk,它具有更好的处理shell变量的工具(也就是说,您可以使用它们而不将它们视为代码):

awk -v var="$variable" '{ n = match($0, /[ \t]/); print substr($0, 1, n - 1) (n <= 1 ? "" : ".") var substr($0, n) }' filename

-v var="$variable"使awk代码知道变量var,其值为$variable",然后awk代码的工作方式如下:

{
  # find the first space or tab in the line (0 if none)
  # (I would use [[:space:]] here, but there are commonly shipped versions
  # of mawk that don't understand POSIX character classes, so for portability
  # I resort to [ \t])
  n = match($0, /[ \t]/)

  # assemble output line accordingly and print it.
  print substr($0, 1, n - 1) (n <= 1 ? "" : ".") var substr($0, n)
}

答案 1 :(得分:0)

awk -F" " '{print $1".21.128\t" $2"\t"$3"\t"$4"\t"$5}' $1