Как я могу удалить весь текст после символа в bash?

147

Как я могу удалить весь текст после символа, в данном случае двоеточие (":"), в bash? Могу ли я удалить толстую кишку тоже? Я понятия не имею, как.

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

Ответы:

135

Пример мог бы быть полезным, но если я вас правильно понял, это сработало бы:

echo "Hello: world" | cut -f1 -d":"

Это преобразует "привет: мир" в "привет".

Эльдад Мор
источник
5
cutработает, но у меня ответ Дениса лучше и гибче. Кто-нибудь знает, порождает ли он новый процесс, как cut?
JoBu1324
3
Лучше использовать встроенные в Bash функции расширения параметров, чем генерировать подоболочки с такими инструментами, как basenameи cut, см. Ответ Денниса ниже
Louis Maddox,
1
cutМожно читать со стандартного ввода, поэтому лучше, особенно если у вас есть очень длинная строка, которую нужно обработать, например, содержимое файла.
Сахас
1
И как это будет применяться к hello: world. Это половина ответа.
К - Токсичность в СО растет.
Это можно сделать, используя синтаксис подстановки, такой же как {var /: / ''}, но он работает только в bash ..
Махеш
266

В Bash (и ksh, zsh, dash и т. Д.) Вы можете использовать расширение параметров, с помощью %которого удаляются символы из конца строки или #удаляются символы из начала строки. Если вы используете один из этих символов, наименьшая соответствующая строка будет удалена. Если вы удвоите символ, самый длинный будет удален.

$ a='hello:world'
$ b=${a%:*}
$ echo "$b"
hello
$ a='hello:world:of:tomorrow'
$ echo "${a%:*}"
hello:world:of
$ echo "${a%%:*}"
hello
$ echo "${a#*:}"
world:of:tomorrow
$ echo "${a##*:}"
tomorrow
Приостановлено до дальнейшего уведомления.
источник
6
Это нативная манипуляция со строкой оболочки, поэтому никакие дополнительные процессы не будут запущены. Ссылка Bash Подстановка параметров , Bash Манипуляция строками и лучше Bash Scripting
Dodzi Dzakuma
@denniswilliamson Как я мог удалить 2 символа после того, как определенная строка, как hello:worldстанет hello:woс использованием ${a%:*}?
3kstc
Отличный ответ, большое спасибо, но было бы неплохо также добавить "${a##*:}"для получения только tomorrow=)
автомат
1
@openCivilisation: Вы , вероятно , нужно использовать регулярные выражения , то: a='hello:world:of:tomorrow'; pattern=''^([^:]*:).*$'; [[$ a = ~ $ pattern]]; echo "$ {BASH_REMATCH [1]}" `. Это соответствует только если есть двоеточие. Если вы хотите, чтобы это было необязательным, необходимо использовать другой шаблон. Объяснение регулярных выражений Bash (и регулярных выражений в целом) выходит за рамки этих комментариев. Вы можете найти другие вопросы, которые обсуждают это или опубликовать свои собственные.
Приостановлено до дальнейшего уведомления.
1
@ kp123: Это первый пример в моем ответе. Во второй раз, когда я показываю это (где убирается «завтра»), это почти та ситуация, о которой вы спрашиваете.
Приостановлено до дальнейшего уведомления.
4
egrep -o '^[^:]*:'
cdhowie
источник
Можете ли вы объяснить, как это интерпретировать, спасибо.
16:46
1
egrepэто grep с -E. Здесь нет разницы с обычным grep. -oинструктирует grep распечатывать только ту часть строки, которая соответствует выражению. ^привязывает матч к началу строки. [^:]*соответствует нулю или более символов, которые не являются :символом. :соответствует персонажу :.
cdhowie
Еще
3

Допустим, у вас есть путь с файлом в этом формате:

/dirA/dirB/dirC/filename.file

Теперь вам нужен только путь, который включает в себя четыре "/". Тип

$ echo "/dirA/dirB/dirC/filename.file" | cut -f1-4 -d"/"

и ваш вывод будет

/dirA/dirB/dirC

Преимущество использования cut заключается в том, что вы также можете вырезать как самый верхний каталог, так и файл (в этом примере), так что если вы наберете

$ echo "/dirA/dirB/dirC/filename.file" | cut -f1-3 -d"/"

ваш вывод будет

/dirA/dirB

Хотя вы можете сделать то же самое с другой стороны строки, в данном случае это не имеет особого смысла, как печатать

$ echo "/dirA/dirB/dirC/filename.file" | cut -f2-4 -d"/"

результаты в

dirA/dirB/dirC

В некоторых других случаях последний случай также может быть полезным. Имейте в виду, что в начале последнего вывода нет символа "/".

Нико Фулнер
источник
2
Что делать, если у вас есть каталог "/resources/views/admin/users/relationships/posts.blade.php", и вы хотите обрезать все после последнего появления "/", учитывая, что вы НЕ знаете, сколько "/ "символы в строке. Поэтому здесь я хотел бы, чтобы вывод был "/ resources / views / admin / users / Relations /" (или даже / resources / views / admin / users / Relations без косой черты). Как бы Вы это сделали?
kp123
-1

обрезать все после последнего экземпляра ":"

cat fileListingPathsAndFiles.txt | grep -o '^.*:'

и если вы хотите отбросить это последнее ":"

cat file.txt | grep -o '^.*:' | sed 's/:$//'

@ kp123: вы хотите заменить :на /(где должно быть двоеточие sed \/)

S Хантер Симпсон
источник