![sed 删除所有内容,直到并包括第一个句点(如果该行上有多个句点)并对整个文件执行此操作](https://linux22.com/image/137688/sed%20%E5%88%A0%E9%99%A4%E6%89%80%E6%9C%89%E5%86%85%E5%AE%B9%EF%BC%8C%E7%9B%B4%E5%88%B0%E5%B9%B6%E5%8C%85%E6%8B%AC%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%8F%A5%E7%82%B9%EF%BC%88%E5%A6%82%E6%9E%9C%E8%AF%A5%E8%A1%8C%E4%B8%8A%E6%9C%89%E5%A4%9A%E4%B8%AA%E5%8F%A5%E7%82%B9%EF%BC%89%E5%B9%B6%E5%AF%B9%E6%95%B4%E4%B8%AA%E6%96%87%E4%BB%B6%E6%89%A7%E8%A1%8C%E6%AD%A4%E6%93%8D%E4%BD%9C.png)
sed
如果该行上有多个句点,则删除直到并包括第一个句点的所有内容,并对整个文件执行此操作。
在 sed 之前:
akamai.com
cdnjs.cloudflare.com
com.cdn.cloudflare.net
sed 之后:
akamai.com
cloudflare.com
cdn.cloudflare.net
答案1
$ sed '/\..*\./s/^[^.]*\.//' file
akamai.com
cloudflare.com
cdn.cloudflare.net
该sed
脚本首先使用正则表达式匹配包含至少两个点的行\..*\.
(也可以编写为[.].*[.]
)。对于与此匹配的行,将执行删除所有内容(直到第一个点)的替换。
使用awk
,与上面相比有点冗长:
$ awk -F '.' -vOFS='.' 'NF > 2 { n=split($0, a); $0=""; for (i=2;i<=n;++i) $(NF+1)=a[i] } 1' file
akamai.com
cloudflare.com
cdn.cloudflare.net
在这里,只要有两个以上的点分隔字段,我们就会将当前行按点分割,然后从中重新创建当前记录,跳过第一个字段。1
末尾的尾随会导致打印每一行(无论是否修改)。
awk
以与解决方案相同的方式更短sed
:
$ awk -F '.' 'NF > 2 { sub("^[^.]*\.", "") } 1' file
akamai.com
cloudflare.com
cdn.cloudflare.net
答案2
您可以使用以下方法来解决此问题:
perl -lpe '$_ = $1 if /\.(.*\..*)/' input-file.txt
其中,我们依赖regex
于一个点.
字符,它可以看到它右边的另一个点。然后,右侧的内容将被捕获并提供$1
并填充到当前行中。-p
然后,选项会将Perl
其带到stdout
以及不匹配的选项。
perl -F\\. -pale '$_ = join ".", splice @F, 1 if @F > 2' input.txt
输入文件通过该选项逐行读取
-p
,自动打印也通过该选项打开。每个记录在点上分割
.
,并且存储在数组中的各个字段通过选项@F
开始索引。0
-a
-l
选项使RS = ORS = "\n"
仅当数组中的元素超过 2 个时
@F
,即当前记录中至少有 2 个点时,我们才会选择这样的记录进行修改。对于这样的记录,该
splice @F, 1
函数会剥离第二个元素,并将它们呈现给函数join
,然后使用点字符将它们连接起来,然后将其填充到$_
当前记录中。然后,该
-p
选项将修改后的当前记录带到 stdout。未修改的记录无论如何都会被静默带到 stdout。
使用GNU sed
我们也可以在不使用捕获括号的情况下完成任务:
sed -e
s/\./\n/2;T
y/\n./.\n/
s/\n/./2g
s/.*\n//
' input.file
输出:
akamai.com
cloudflare.com
cdn.cloudflare.net