Удалить одно или несколько полей, разделенных «-», в конце строки

8

Я собираюсь проанализировать данные 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 После того, как проанализировал, я изменю пространство, чтобы быть hypen -назад.

Кто-нибудь знает лучшую практику или однострочную команду оболочки для ее анализа? Спасибо всем

Ники Пафф
источник

Ответы:

10

с sedвами можно сделать:

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

сопоставьте шаблон как -anythingдважды (...){2}от конца $каждой строки и удалите его.

αғsнιη
источник
7
$ 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:]]*в конце каждой строки.

С 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как это не переносимо, и его следует избегать (нет гарантии, что оно изменит текущую запись). Это не будет работать с BSD awk, например.

При использовании стандарта awk, не прибегая к использованию 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
Кусалананда
источник
4

С revи cut:

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

Переверните строки, cutполе 3 до конца строки и снова переверните текст обратно.


С grep(и PCRE):

grep -Po '.*(?=(-[^-]*){2}$)' file
  • -Pиспользуйте совместимые с Perl регулярные выражения с положительным прогнозом, (?...)содержащим два совпадения, за -которыми следуют любые не- -символы
  • -o печатать только совпадающие детали
Фредди
источник
4
$ perl -F- -lane 'print join "-", @F[0..($#F-2)]' googleapis.txt
bucket,abc-def-ghi
bucket,dde-wwq-ooi
instance,jkl-mno-1-zzz
disk,pqr-stu-10-kuy

Это автоматически разбивает каждую входную строку в массив @F, используя разделитель -.

Затем он печатает фрагмент массива всех, кроме двух последних полей, повторно объединенных -символами.

саз
источник
1

Вы можете сделать это различными способами, как показано здесь:

$ 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
Ракеш Шарма
источник