删除行尾的一个或多个字段,以“-”分隔

删除行尾的一个或多个字段,以“-”分隔

我要解析数据googleapis.txt

bucket,abc-def-ghi-45gjd4-wwxis
bucket,dde-wwq-ooi-66ciow-po22q
instance,jkl-mno-1-zzz-68dkakw-oo9w8
disk,pqr-stu-10-kuy-l2oxapw-rp4lt

我期望像下面这样的结果

bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

我想我必须更改-为空格,然后运行此命令

cat googleapis.txt | awk '{$NF="";sub(/[ \t]+$/,"")}1' | awk '{$NF="";sub(/[ \t]+$/,"")}1'

我从这个得到了https://stackoverflow.com/a/27794421/8162936 解析后,我将把空格改为连字符-

有谁知道解析它的最佳实践或单行 shell 命令吗?谢谢大家

答案1

sed你一起可以做:

sed -E 's/(-[^-]*){2}$//' infile

从每行末尾匹配-anything两次类似的模式并将其删除。(...){2}$

答案2

$ sed 's/-[[:alnum:]]*-[[:alnum:]]*$//' file
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

这用于sed匹配每行上最后两个破折号分隔的子字符串并将其删除。 [[:alnum:]]将匹配任何字母数字字符。

您可以将其缩短为

sed 's/\(-[[:alnum:]]*\)\{2\}$//' file

-[[:alnum:]]*即,匹配并删除每行末尾的两组ath。

使用GNU awk,你也可以这样做

$ awk -F '-' 'BEGIN { OFS=FS } { NF -= 2; print }' file
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

NF这样的改变是不可移植的,应该避免(不能保证它会改变当前记录)。awk例如,它不适用于 BSD 。

使用 standard awk,而不诉诸 using sub()(这只是模仿sed),您将必须从您想要使用的字段重新创建当前记录(在我们的例子中,除了最后两个破折号分隔的字段之外的所有字段):

$ awk -F '-' 'BEGIN { OFS=FS } { nf = split($0,a) - 2; $0=""; for (i=1; i<=nf; ++i) $i = a[i]; print }' file
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

答案3

revcut

rev file | cut -d'-' -f3- | rev

将行、cut字段 3 反转到行尾,然后再次反转文本。


使用grep(和 PCRE):

grep -Po '.*(?=(-[^-]*){2}$)' file
  • -P使用与 perl 兼容的正则表达式,其中(?...)包含两个匹配项,-后跟任何非-字符
  • -o只打印匹配的部分

答案4

您可以通过多种方式完成此操作,如下所示:

$ perl -F- -pale '$"="-";$#F-=2;$_="@F"' file

在破折号上分割线,将数组元素连接器设置为破折号,剪辑最后两个元素,并将当前行设置为用破折号连接的数组。

$ awk -F- '{
   t = $1
   for ( i=2; i<NF-1; i++ ) t = t FS $i
   $0 = t
}1' file

这是普通字符串处理:

$ perl -lne 'print substr($_, 0, rindex($_,"-",-1+rindex($_,"-")))' file

$ sed -ne '
   y/-/\n/
   :a;h;s/\n/-/;/\n.*\n/ba
   g;P
' file

结果:

bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

相关内容