解释

解释

我有一个文本文件。看起来像:

www.ac.com has address 6.1.1.146 www.ac.com is an alias for ac.com. www.ac.com is an alias for ac.com.
www.ba.net is an alias for www-bn.gs.ba.com. www-bn.gs.ba.com has address 11.28.11.4 ;; connection timed out; no servers could be reached

我想提取之前和之后的列has address,并用逗号分隔它们。所以我想得到:

www.ac.com,6.1.1.146
www-bn.gs.ba.com,11.28.11.4

这个怎么做?我已经尝试过awk '{print $1,$4}' myfile > newfile,但它不能很好地工作,因为并不总是我想要的情况是在第 1 列和第 4 列中。感兴趣的列可以有所不同,但总是用 分隔has address

答案1

使用grepsed

grep -o '[^ ]* has address [^ ]*' | sed 's/ has address /,/'

我喜欢这个,因为它很简单。


解释:

grep-o将仅输出找到以下模式的每一行的匹配 ( ) 部分:

  • 任何非空格 ( [^ ]*)的字符,has address后跟任何非空格 ( [^ ]*) 的字符。

sed将简单地替换has address,

答案2

sed

sed -r 's/(.* |^)([^ ]*) has address ([^ ]*)( .*|$)/\2,\3/' myfile > newfile

解释

  • sed -r 's/foo/bar/' myfile > newfilesed与“扩展正则表达式”(-r)一起使用,因此我们不需要转义()下面的捕获组。将出现的 替换foobar。读取myfile并写入newfile
  • (.* |^)([^ ]*) has address ([^ ]*)( .*|$):查找字符串has address,前后各有一个空格。在此之前和之后应该是一个不包含空格的字符串,我们应该将其捕获在一个 group 中([^ ]*)。前导单词之前应该是一个空格(前面有任何内容.*)或行的开头,即(.* |^)。接下来的单词后面应该是一个空格(后面跟着任何内容.*),或者是行尾,即( .*|$)
  • \2,\3:上面的表达式捕获整行,因此将其替换为第二个和第三个捕获组,即单词 before 和 after has address

答案3

perl -nE '/(\S+) has address (\S+)/ and say "$1,$2"' x

答案4

awk

awk -v OFS=, '
  {
    for(i=1;i<NF;i++){
      j=i+1;
      if ($i=="has" && $j=="address") {
        domain=i-1;
        ip=i+2;
        print $domain,$ip;
        break;
      }
    }
  }'

循环遍历字段,如果找到“has”并且下一个字段是“address”,它将打印该字段之前和之后的字段作为,输出字段分隔符。

相关内容