Как удалить текст после '-'?

У меня есть список файлов (в основном это .deb пакеты). Предположим:

abc-de-1.2.3-1.deb fgh-ij-4.5.6-2.deb klm-no-7.8.9-3.deb pqrs-10.11.12-4.deb ...

Как вы можете видеть, некоторые имена файлов имеют номера после -, в то время как другие имеют некоторый текст после -, а затем цифры после следующего -. [ ! d1]

Есть ли способ удалить все, начиная с чисел, включая -, т. е.

abc-de fgh-ij klm-no pqrs ...

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

6
задан 23 July 2017 в 10:04

10 ответов

Если вы можете использовать первый номер для определения того, что хотите удалить каждый раз, вы можете использовать:

$ sed 's/-[0-9].*//' file
abc-de
fgh-ij
klm-no
pqrs

Примечания

s/old/new/ заменить [ f3] с new [0-9] некоторой цифрой .* любое число любых символов
8
ответ дан 22 May 2018 в 20:16
  • 1
    Будет ли он работать, если список имен файлов находится в текстовом файле? – Raphael 23 July 2017 в 09:34
  • 2
    @Raphael вы хотите отредактировать сам список или имена только файлов в списке? Если последний, где файлы? Являются ли они в каталоге с другими вещами, которые вы не хотите переименовывать, и которые нельзя отличить от них с помощью групповых шаблонов оболочки или в нескольких каталогах? – Zanna 23 July 2017 в 09:37
  • 3
    У меня есть имена файлов в файле txt, и я хочу редактировать имена в этом файле, т. Е. Я хочу редактировать список. – Raphael 23 July 2017 в 09:41
  • 4
    @Raphael ОК, я не понимаю, что именно вы хотите изменить. Фактические файлы или только список, который у вас есть? Вы хотите, чтобы команда читала список и переименовывала debs, или вы хотите, чтобы команда только редактировала ваш список и не касалась реальных deb? – Sergiy Kolodyazhnyy 23 July 2017 в 09:43
  • 5
    @Raphael вы можете использовать такое же регулярное выражение для утилиты переименования, если файлы действительно существуют rename 's/-[0-9].*//' *.deb – Avinash Raj 24 July 2017 в 08:52

Если вы можете использовать первый номер для определения того, что хотите удалить каждый раз, вы можете использовать:

$ sed 's/-[0-9].*//' file abc-de fgh-ij klm-no pqrs

Примечания

s/old/new/ заменить old с new [0-9] некоторой цифрой .* любое число любых символов
8
ответ дан 18 July 2018 в 09:50

Используя grep с регулярными выражениями Perl:

$ grep -Po "^[a-z-]*(?=-[0-9])" filename
abc-de
fgh-ij
klm-no
pqrs
6
ответ дан 22 May 2018 в 20:16

Perl

$ perl -lne 's/([[:digit:]].*)//;s/-$//;print' input.txt                                                            
abc-de
fgh-ij
klm-no
pqrs

Выполняет две замены: одну, чтобы удалить все, что начинается с цифры, и удаляет трейлинг -. Используйте -i дополнительные опции для редактирования исходного файла, например $ perl -i -lne 's/([[:digit:]].*)//;s/-$//;print' input.txt

. Альтернативно, с жадным несоответствием и группировкой цифр:

$ perl -lne 's/^(\D*)-.*/\1/;print' input.txt                                                                                                        
abc-de
fgh-ij
klm-no
pqrs

AWK

$ awk -F '-' '{s=$1;for(i=2;i<=NF;i++) if($i~/[0-9].*/){print s;next}else{s=s"-"$i}}' input.txt 
abc-de
fgh-ij
klm-no
pqrs
]

Как это работает, мы рассматриваем - как разделитель для полей, а затем итерацию по каждой строке. Мы «кэшируем» первое поле и перемещаемся по итерации с использованием цикла for. На каждой итерации мы проверяем, не содержит ли столбец номер, который мы вставляем в переменную s.

Используйте > new_file.txt в конце для перенаправления вывода в новый файл.

Python [ ! d6]
#!/usr/bin/env python
import sys,re

with open(sys.argv[1]) as f:
    for line in f:
        tokens = re.split("-|\.",line.strip().replace(".deb",""))
        words_only = filter(lambda x: not x.isdigit(),tokens)
        print("-".join(words_only))

Используя re.split(), мы разбиваем каждую строку на список токенов и фильтруем только нецифровые маркеры.

В качестве альтернативы, это команда с одним слоем. Это не требует предварительного предупреждения в случае отсутствия цифры в строке, поэтому используйте это, только если вы уверены, что все строки содержат числа.

$ python -c 'import re,sys;f=open(sys.argv[1]);print("\n".join([ l[:re.search(r"\d",l).start()-1] for l in f]))' input.txt

Потенциальные числа в именах пакетов

hvd должным образом отметил в комментариях, что иногда могут быть целые числа в именах пакетов, что может представлять трудности при анализе входного файла, в то время как имена версий обычно имеют точки в них. Имея это в виду, команды могут быть несколько изменены, чтобы противостоять этому:

$ perl -lne 's/\d*\..*//;s/-$//;print' input.txt

$ awk '{gsub(/[0-9]*\..*/,"");print substr($0,0,length($0)-1)};' input.txt                                                                           

$ python -c 'import re,sys;f=open(sys.argv[1]);print("\n".join([ l[:re.search(r"\d*\.",l).start()-1] for l in f]))' input.txt
4
ответ дан 22 May 2018 в 20:16
  • 1
    Ха-ха, хорошо, но версия python может быть немного многословной для задания :) – Jacob Vlijm 23 July 2017 в 10:27
  • 2
    @JacobVlijm, ну, я могу превратить его в один лайнер или использовать re.match, но это повторяет то же самое, что и sed или perl отвечает – Sergiy Kolodyazhnyy 23 July 2017 в 10:44
  • 3
    Ваш ответ Perl предполагает, что первая цифра сразу же будет следовать за символом -, но вход OP выглядит как имена пакетов и версии, и это не редкость в том, что имена пакетов также содержат цифры. – hvd 23 July 2017 в 12:13
  • 4
    @hvd хорошая точка, однако, вероятно, следует прокомментировать OP, а не мой ответ (или другие ответы, если на то пошло). Они спросили remove everything starting from the numbers including the -, поэтому я представил то, что они попросили. Если у них есть другие типы пакетов в списке, я могу пересмотреть ответ, но OP должен явно сказать это – Sergiy Kolodyazhnyy 23 July 2017 в 12:20
  • 5
    @SergiyKolodyazhnyy Вопрос задает «числа после -» в предложении перед тем, о котором вы говорите, так лично, я думаю, что вопрос достаточно ясен, как есть. – hvd 23 July 2017 в 12:26

Через awk,

awk -F'-[0-9]' '{print $1}' file

В awk мы также можем передать регулярное выражение в качестве аргумента в полевой разделитель -F. Таким образом, это разделило бы каждую строку на ту часть, где соответствует регулярное выражение.

Пример:

$ echo 'abc-de-1.2.3-1.deb' | awk -F'-[0-9]' '{print $1}'
abc-de
4
ответ дан 22 May 2018 в 20:16

Я буду предполагать, так как вы предположили, что файлы являются пакетами DEB, тогда, возможно, вам нужно что-то вроде:

dpkg-query -f '${Package}\n' -W 'gnome*'

Где вместо gnome* вы можете заменить любой шаблон , Я не уверен, что такое соглашение об именах архивов DEB, но если это архивы DEB, лучше всего полагаться на dpkg, чтобы дать вам имя пакета.

И если это DEB архивных файлов (в вашей системе), вы можете использовать:

dpkg-deb --showformat='${Package}\n' -W some-file.deb 
1
ответ дан 22 May 2018 в 20:16

Через awk,

awk -F'-[0-9]' '{print $1}' file

В awk мы также можем передать регулярное выражение в качестве аргумента в полевой разделитель -F. Таким образом, это разделило бы каждую строку на ту часть, где соответствует регулярное выражение.

Пример:

$ echo 'abc-de-1.2.3-1.deb' | awk -F'-[0-9]' '{print $1}' abc-de
4
ответ дан 18 July 2018 в 09:50

Используя grep с регулярными выражениями Perl:

$ grep -Po "^[a-z-]*(?=-[0-9])" filename abc-de fgh-ij klm-no pqrs
6
ответ дан 18 July 2018 в 09:50

Perl

$ perl -lne 's/([[:digit:]].*)//;s/-$//;print' input.txt abc-de fgh-ij klm-no pqrs

Выполняет две замены: одну, чтобы удалить все, что начинается с цифры, и удаляет трейлинг -. Используйте -i дополнительные опции для редактирования исходного файла, например $ perl -i -lne 's/([[:digit:]].*)//;s/-$//;print' input.txt

. Альтернативно, с жадным несоответствием и группировкой цифр:

$ perl -lne 's/^(\D*)-.*/\1/;print' input.txt abc-de fgh-ij klm-no pqrs

AWK

$ awk -F '-' '{s=$1;for(i=2;i<=NF;i++) if($i~/[0-9].*/){print s;next}else{s=s"-"$i}}' input.txt abc-de fgh-ij klm-no pqrs ]

Как это работает, мы рассматриваем - как разделитель для полей, а затем итерацию по каждой строке. Мы «кэшируем» первое поле и перемещаемся по итерации с использованием цикла for. На каждой итерации мы проверяем, не содержит ли столбец номер, который мы вставляем в переменную s.

Используйте > new_file.txt в конце для перенаправления вывода в новый файл.

Python [ ! d6] #!/usr/bin/env python import sys,re with open(sys.argv[1]) as f: for line in f: tokens = re.split("-|\.",line.strip().replace(".deb","")) words_only = filter(lambda x: not x.isdigit(),tokens) print("-".join(words_only))

Используя re.split(), мы разбиваем каждую строку на список токенов и фильтруем только нецифровые маркеры.

В качестве альтернативы, это команда с одним слоем. Это не требует предварительного предупреждения в случае отсутствия цифры в строке, поэтому используйте это, только если вы уверены, что все строки содержат числа.

$ python -c 'import re,sys;f=open(sys.argv[1]);print("\n".join([ l[:re.search(r"\d",l).start()-1] for l in f]))' input.txt

Потенциальные числа в именах пакетов

hvd должным образом отметил в комментариях, что иногда могут быть целые числа в именах пакетов, что может представлять трудности при анализе входного файла, в то время как имена версий обычно имеют точки в них. Имея это в виду, команды могут быть несколько изменены, чтобы противостоять этому:

$ perl -lne 's/\d*\..*//;s/-$//;print' input.txt $ awk '{gsub(/[0-9]*\..*/,"");print substr($0,0,length($0)-1)};' input.txt $ python -c 'import re,sys;f=open(sys.argv[1]);print("\n".join([ l[:re.search(r"\d*\.",l).start()-1] for l in f]))' input.txt
4
ответ дан 18 July 2018 в 09:50

Я буду предполагать, так как вы предположили, что файлы являются пакетами DEB, тогда, возможно, вам нужно что-то вроде:

dpkg-query -f '${Package}\n' -W 'gnome*'

Где вместо gnome* вы можете заменить любой шаблон , Я не уверен, что такое соглашение об именах архивов DEB, но если это архивы DEB, лучше всего полагаться на dpkg, чтобы дать вам имя пакета.

И если это DEB архивных файлов (в вашей системе), вы можете использовать:

dpkg-deb --showformat='${Package}\n' -W some-file.deb
1
ответ дан 18 July 2018 в 09:50

Другие вопросы по тегам:

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