Як я можу видалити весь текст після символу в bash?


147

Як я можу видалити весь текст після символу, у цьому випадку двокрапки (":"), в басі? Чи можна видалити товсту кишку? Я поняття не маю.

Відповіді:


134

Приклад може бути корисним, але якби я вас правильно зрозумів, це спрацює:

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

Це перетворить "привіт: світ" у "привіт".


5
cutпрацює, але я відповідь Денніса краща і гнучкіша. Хтось знає, чи породжує він такий новий процес cut?
JoBu1324

3
Краще скористатися вбудованими функціями розширення параметрів Баша, ніж генерувати такі підпрограми, які працюють під керуванням інструментів, basenameі cut, див. Відповідь Денніса нижче
Луї Маддокс

1
cutможна читати зі stdin, тому краще, особливо якщо у вас дуже довгий рядок, який потрібно обробити, як і вміст файлу.
Сахас

1
І як би це було застосовано hello: world. Це половина відповіді.
K - Токсичність в SO зростає.

Це можна зробити за допомогою синтаксису підстановки також, як {var /: / ''}, але працює лише в bash ..
Mahesh,

264

У 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
Це натисна маніпуляція з рядком оболонки, тому ніяких додаткових процесів не буде породжено. Довідкова параметр Заміна , Маніпуляція стрункою баш та краща сценарій баш
Dodzi Dzakuma

@denniswilliamson Як я міг видалити 2 символи після того, як певний рядок, як hello:worldце стане hello:wo, використовуватися ${a%:*}?
3kstc

Чудова відповідь, велике спасибі, але буде непогано також додати "${a##*:}"для отримання лише tomorrow=)
avtomaton

1
@openCivilisation: Ви , ймовірно , потрібно використовувати регулярні вирази , то: a='hello:world:of:tomorrow'; pattern=''^([^:]*:).*$'; [[$ a = ~ $ pattern]]; echo "$ {BASH_REMATCH [1]}" `. Це відповідає лише за наявності двокрапки. Якщо ви хочете, щоб це було необов’язково, потрібно було б використовувати інший візерунок. Пояснення реджексів Баша (і загально-регулярних виразів) виходить за рамки цих коментарів. Ви можете знайти інші питання, які обговорюють це, або опублікувати своє.
Призупинено до подальшого повідомлення.

1
@ kp123: Це перший приклад у моїй відповіді. Другий раз, коли я показую це (де "завтра" знято), це майже саме та ситуація, про яку ви питаєте.
Призупинено до подальшого повідомлення.


4
egrep -o '^[^:]*:'

чи можете ви пояснити, як це інтерпретувати? Дякую
rɑːdʒɑ

1
egrepгреп -E. Тут немає різниці від звичайних grep. -oвказує grep друкувати лише ту частину рядка, яка відповідає виразу. ^прив’язує матч до початку рядка. [^:]*відповідає нулю або більше символів, які не є :символом. :відповідає персонажу :.
cdhowie

Ще раз дякую за пояснення
rɑːdʒɑ

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", і ви хочете обрізати все після ОСТАНОГО появи "/", враховуючи, що ви НЕ знаєте, скільки "/ "символів є в рядку. Тож тут я хотів би, щоб результатом було "/ ресурси / перегляди / адміністратор / користувачі / відносини /" (або навіть / ресурси / погляди / адміністратор / користувачі / відносини без останньої косої риски). Як би ти це зробив?
kp123

-1

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

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

і якщо ви хотіли скинути останнє ":"

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

@ kp123: ви б хотіли замінити :на /(де повинна бути двокрапка \/)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.