У меня есть список файлов (в основном, они .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
...
Поскольку Вы видите, что некоторые имена файлов имеют числа после a -
в то время как у других есть некоторый текст после a -
и затем числа после следующего -
.
Есть ли любые способы удалить все начинающее с чисел включая -
, т.е.
abc-de
fgh-ij
klm-no
pqrs
...
Я хочу отредактировать список, не переименовывают файлы.
Если Вы можете использовать первое число для идентификации то, что Вы хотите удалить каждый раз, когда Вы могли использовать:
$ sed 's/-[0-9].*//' file
abc-de
fgh-ij
klm-no
pqrs
s/old/new/
замена old
с new
[0-9]
некоторая цифра.*
любое количество любых символовИспользуя grep
с регулярными выражениями Perl:
$ grep -Po "^[a-z-]*(?=-[0-9])" filename
abc-de
fgh-ij
klm-no
pqrs
$ 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 -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
в конце для перенаправления вывода в новый файл.
#!/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
Через awk,
awk -F'-[0-9]' '{print $1}' file
В awk мы можем также передать regex как аргумент Разделителю полей -F
. Таким образом, это разделило бы каждую строку на части, где regex соответствует.
Пример:
$ echo 'abc-de-1.2.3-1.deb' | awk -F'-[0-9]' '{print $1}'
abc-de
Я выскажу предположение, так как Вы предположили, что файлы являются пакетами DEB, затем, возможно, Вы хотели что-то как:
dpkg-query -f '${Package}\n' -W 'gnome*'
Где, вместо gnome*
, Вы могли заменить любым шаблоном. Я не уверен, что точно конвенция для именования архивов DEB, но если это - архивы DEB, вероятно, лучше полагаться dpkg
дать Вам имя пакета.
И если это - архивные файлы DEB (в Вашей системе), то Вы могли использовать:
dpkg-deb --showformat='${Package}\n' -W some-file.deb