-1

在 shell 脚本中,我想使用 sed 将1bc1034gf45dna22(总共 16 个字符)替换为1b:c1:03:4g:f4:5d:na:22(用冒号分隔)。

编辑

我试过了

sed 's/\w{2}/\w{2}:/g' a.txt > b.txt

哪里a.txt

1bc1034gf45dna22
4

7 回答 7

2

边缘案例太多

Sed 不是这项工作的理想工具,因为有太多的边缘情况。如果您有非常规则的数据和已知的语料库,那很好,但在某些情况下,您需要更强大的东西,可以在匹配/捕获感兴趣的文本后独立地作用于一行。例如,给定一个包含以下内容的输入文件:

foo 1bc1034gf45dna22 bar

您可能需要提取第二列,对其进行转换,然后将其替换到位。您可以使用 Ruby 执行此操作,如下所示:

$ echo 'foo 1bc1034gf45dna22 bar' |
ruby -pe '
  if /(?<str>\p{Alnum}{16})/ =~ $_
    $_.sub!(str, str.scan(/../).join(?:))
  end'

这正确地产生:

foo 1b:c1:03:4g:f4:5d:na:22 bar
于 2013-09-06T09:02:13.390 回答
1

这可能对您有用(GNU sed):

sed 's/\w\w\B/&:/g' file
于 2013-09-06T15:28:56.640 回答
1

sed -e 's/../&:/g' -e 's/:$//' a.txt > b.txt

或者

sed -e 's/\(..\)/\1:/g' -e 's/:$//' a.txt > b.txt

为你工作?

于 2013-09-06T17:44:40.890 回答
0

为什么不 sed 's/1bc1034gf45dna22/1b:c1:03:4g:f4:5d:na:2/g' file呢?

于 2013-09-06T07:48:38.077 回答
0

在任何 GNU/Linux 发行版上使用 GNU/sed,您都可以使用扩展的正则表达式。这会将任意长度的字符串转换为每两个字母用冒号分隔的字符串:

echo 1bc1034gf45dna22 | sed -re 's/(\w{2})/\1:/g' -e 's/:$//'

在您的 AIX 平台上,您可以利用 awk:

echo 1bc1034gf45dna22 | awk '
  BEGIN { FS=""; ORS=""; } 
  {
    for (i=1; i <=NF; i++) {
      if (i > 1 && (i + 1) % 2 == 0) { 
        print(":"); 
      }  

      print($i);
    }
  }'
于 2013-09-06T08:04:16.200 回答
0

你可以:

sed -i 's/\(\w\{2\}\)/\1:/g' file

这也会在字符串的末尾附加一个 :。由于我们不能在 sed 正则表达式语法中使用积极的前瞻,因此我们需要:

sed -i 's/:$//g' file

请注意,我们对 sed 使用了就地编辑,因此文件将以这种方式更改。

或者,您可以使用 perl 来使用 /(\w{2})(?=\w{2})/$1:/g 的正则表达式

于 2013-09-06T08:05:37.040 回答
0

好吧,总是有蛮力方法:

sed 's/\<'\
'\([0-9a-z][0-9a-z]\)'\
'\([0-9a-z][0-9a-z]\)'\
'\([0-9a-z][0-9a-z]\)'\
'\([0-9a-z][0-9a-z]\)'\
'\([0-9a-z][0-9a-z]\)'\
'\([0-9a-z][0-9a-z]\)'\
'\([0-9a-z][0-9a-z]\)'\
'\([0-9a-z][0-9a-z]\)'\
'\>/\1:\2:\3:\4:\5:\6:\7:\8/g'

在延续线上没有前导空格的情况下,shell 将字符串正确地粘贴在一起。

于 2013-09-06T15:47:53.313 回答