假设我有很多ip号码(每行2个ip号,用空格分隔)可以查看(这里有两行):
67.21.89.48.1623 139.91.131.115.110
211.47.82.64 139.91.134.123.445
其中一个可能没有端口,因此周期数永远不会一致。我只想要第一个(没有端口)的ip号和第二个的端口号(没有ip号)。所以看起来应该是这样的:
67.21.89.48 110
211.47.82.64 445
或者看起来像这样:
67.21.89.48.110
211.47.82.64.445
只要我知道IP和端口所在的位置,这并不重要。
我一直在使用这样的东西:
cut -d'.' -f1-4,9 < file.txt
但这只适用于一致数量的时期。有什么方法可以从后面切割?
答案 0 :(得分:3)
详细格式:
perl -n -e 'print "$1 $2\n" if m/^
((?:\d+\.){3}\d+) # IPv4 address
(?:\.\d+)? # Optional port
\s+ # White space
(?:(?:\d+\.){4}) # IPv4 address plus dot
(\d+) # Port number
\s*$ # Optional white space
/x' perl.data
一衬垫:
perl -ne 'print "$1 $2\n" if m/^((?:\d+\.){3}\d+)(?:\.\d+)? (?:(?:\d+\.){4})(\d+)\s*$/'
如果第二个条目有端口号,则只打印任何内容;如果没有,则跳过该行。
如果您愿意,可以使IP地址和端口号识别对称(即使不打印第二个IP地址):
perl -n -e 'print "$1 $4\n" if m/^ \s* # Optional white space
((?:\d+\.){3}\d+) # IPv4 address
(?:\.(\d+)) ? # Optional Port number
\s+ # White space
((?:\d+\.){3}\d+) # IPv4 address
(?:\.(\d+)) # Mandatory Port number
\s* $ # Optional white space
/x' perl.data
我已将\d+
用于“一个或多个数字”;对于IPv4点分十进制地址组件,可以将\d{1,3}
表示为“一到三位数”,端口号可以是\d{1,5}
表示“一到五位”。
如果您真的注重细节,甚至可以更精确地限制数字范围,但这可能不值得。这是正则表达式处理的常见特征;你可以处理一些对手头的工作足够好的东西 - 而不必处理恶意可能给你带来的每一种可能的变化。你必须对做什么做出判断。
答案 1 :(得分:2)
正如Jonathan在评论中指出的那样,使用cut
会非常复杂,因为您需要的列数可能会有所不同。
以下是sed
中的示例:
$ echo "67.21.89.48.1623 139.91.131.115.110
211.47.82.64 139.91.134.123.445" | sed -r 's/^(([0-9]{1,3}\.){3}[0-9]{1,3})(.*)\.([0-9]{1,4})$/\1 \4/'
67.21.89.48 110
211.47.82.64 445
您可以将其运行为:
sed -r 's/^(([0-9]{1,3}\.){3}[0-9]{1,3})(.*)\.([0-9]{1,4})$/\1 \4/' logfile.txt
[0-9]{1,3}\.){3}[0-9]{1,3}
可能是IP地址的一个蹩脚的正则表达式,但它是我能想到的第一个。你可以用更聪明的东西替换它。
也许你甚至不需要检查点之间的内容,只需要在第4个时段之前和最后一个时段之后取出所有内容。