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

У меня нет компьютера для тестирования, но это должно работать с gnused:

sed 'H;1h;$!d;g;s/.*pattern1/@@@/;s/\n[^\n]*pattern2[^\n]*//;H;g;s/\(.*pattern1\).*@@@/\1/'

Вместо @@@используйте любую последовательность символов, о которой известно, что она не является частью файла.

8
30.09.2019, 03:16
5 ответов

с помощью sedможно сделать:

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

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

10
27.01.2020, 20:08
$ 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
7
27.01.2020, 20:08

С revиcut:

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

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


Сgrep(и PCRE):

grep -Po '.*(?=(-[^-]*){2}$)' file
  • -Pиспользовать совместимые с perl -регулярные выражения с положительным опережением (?...), содержащие два совпадения -, за которыми следуют любые не--символы
  • -oпечатать только совпадающие детали
4
27.01.2020, 20:08
$ 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с использованием разделителя -.

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

4
27.01.2020, 20:08

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

$ 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
1
27.01.2020, 20:08

Теги

Похожие вопросы