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