Вырезать одно слово перед разделителем — Bash

Как использовать cut, чтобы получить одно слово перед разделителем? Например, у меня есть строка ниже в file.txt:

один два три четыре пять шесть семь

когда я использую команду cut ниже:

cat file.txt | cut -d ':' -f1

...тогда я получаю все до разделителя; то есть:

раз, два, три, четыре, пять

...но я хочу только "пятерку"

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

Спасибо!


person sidman    schedule 08.10.2015    source источник
comment
Ваша причина нежелания использовать awk не имеет смысла.   -  person Amadan    schedule 08.10.2015
comment
cut -d ':' -f1 file.txt | rev | cut -d' ' -f 1 | rev будет работать, если вы действительно хотите использовать cut, хотя было бы намного проще использовать awk или sed   -  person 123    schedule 08.10.2015
comment
мой файл может измениться, как я уже упоминал, например, s='one Five: two three Four Seven Six' , поэтому я не хочу использовать фиксированную печать $5.   -  person sidman    schedule 08.10.2015
comment
Амандан, это работает! и я выучил новую команду rev :)   -  person sidman    schedule 08.10.2015
comment
Был не я. Я только что сказал, что awk — это гораздо больше, чем print $5.   -  person Amadan    schedule 08.10.2015
comment
Понял, спасибо Амандан! Я новичок в переполнении стека, не знаю, как я могу проголосовать за ваш ответ, но большое спасибо!   -  person sidman    schedule 08.10.2015


Ответы (4)


Чистый баш:

s='one two three four five: six seven'
w=${s%%:*}                 # cut off everything from the first colon
l=${w##* }                 # cut off everything until last space
echo $l
# => five

(Если в вашем файле есть одно двоеточие, s=$(grep : file) должно установить вашу начальную переменную)

person Amadan    schedule 08.10.2015
comment
Почему вы делаете кучу переменных? - person 123; 08.10.2015
comment
@999999999999999999999999999999: Зачем тебе все эти широкие девятки? :P (Для серьезного ответа - ясность, я полагаю. Но если бы я действительно думал о том, что я делаю, я бы назвал их string, words, lastword или что-то подобное.) - person Amadan; 09.10.2015

Поскольку здесь вам нужно использовать более одного разделителя полей, на помощь приходит awk:

s='one two three four five: six seven'
awk -F '[: ]' '{print $5}' <<< "$s"
five

РЕДАКТИРОВАТЬ: Если ваши позиции в поле могут измениться, попробуйте это awk:

awk -F: '{sub(/.*[[:blank:]]/, "", $1); print $1}' <<< "$s"
five

Вот однострочный BASH, чтобы получить это в одной команде:

[[ $s =~ ([^: ]+): ]] && echo "${BASH_REMATCH[1]}"
five
person anubhava    schedule 08.10.2015
comment
Спасибо, анубхава, мой файл может измениться, как я уже упоминал, например, s='one Five: two three Four Seven Six' , поэтому я не хочу использовать фиксированную печать $5. - person sidman; 08.10.2015
comment
Если ваши позиции в поле могут измениться, попробуйте мою отредактированную команду awk. - person anubhava; 08.10.2015
comment
Добро пожаловать, также проверьте мой однострочник BASH, который, я думаю, подойдет для вашей задачи. - person anubhava; 08.10.2015

вы можете сделать что-то вроде этого:

cat file.txt | while read line
do
  for word in $line
    do
      if [ `echo $word | grep ':$'` ] then;
        echo $word
      fi
    done
done

если это последовательная структура (с разным количеством слов в строке), вы можете изменить первую строку на:

cat file.txt | cut -d':' -f1 | while read line
do ...

и таким образом избежать обработки ':' справа от разделителя

person Adi    schedule 08.10.2015

Пытаться

echo "one two three four five: six seven" | awk -F ':' '{print $1}' | awk '{print $NF}'

Это всегда будет печатать последнее слово перед первым : независимо от того, что происходит

person Zloj    schedule 08.10.2015