У меня есть файл с именем yeet.d
, который выглядит так
JET_FUEL = /steel/beams
ABC_DEF = /michael/jackson
....50 rows later....
SHIA_LEBEOUF = /just/do/it
....73 rows later....
GIVE_FOOD = /very/hungry
NEVER_GONNA = /give/you/up
Я знаком с параметрами f and d
команды cut
. Параметр f
позволяет указать, из каких столбцов извлекать данные, а параметр d
позволяет указать разделители.
Я хочу, чтобы этот вывод возвращался с помощью команды cut
.
/just/do/it
Насколько я знаю, это часть команды, которую я хочу ввести:
cut -f1 -d= yeet.d
Учитывая, что мне нужны значения справа от знака равенства, со знаком равенства в качестве разделителя. Однако это вернет:
/steel/beams
/michael/jackson
....50 rows later....
/just/do/it
....73 rows later....
/very/hungry
/give/you/up
Что больше, чем то, что я хочу.
Как мне использовать команду cut
, чтобы вернуть Только/just/do/it
и ничего больше из ситуации выше? Это отличается от Как получить предпоследнее поле из команды вырезания, потому что я хочу выбрать строку в большом файле, а не только рядом с концом или началом.
Это зависит от того, как вы хотите идентифицировать нужную строку.
Узнать его можно по номеру строки. В этом случае вы можете использовать sed
cut -f2 -d= yeet.d | sed '53q;d'
Это извлекает 53-ю строку.
Или вы можете определить его по ключевому слову. В этом случае используйте grep
cut -f2 -d= yeet.d | grep just
Это извлекает все строки, содержащие слово только что.
Похоже, это было бы проще выразить с помощью awk
...
# awk -v _s = "${_string}" '$3 == _s {print $3}' "${_path}"
## Above could be more _scriptable_ form of bellow example
awk -v _search = "/just/do/it" '$3 == _search {print $3}' <<'EOF'
JET_FULE = /steal/beams
SHIA_LEBEOUF = /just/do/it
NEVER_GONNA = /give/you/up
EOF
## Either way, output should be similar to
## /just/do/it
Бит -v _something = "Some Thing"
позволяет передавать переменные Bash в awk
Бит $3 == _search
сообщает awk
совпадению только тогда, когда столбец 3
равен строке search
$0 ~ _search
Бит {print $3}
сообщает awk
в print
столбец 3
для любых совпадений
И бит <<'EOF'
говорит Bash ничего не расширять в пределах открытия и закрытия EOF
теги
... однако приведенное выше по-прежнему будет выводить повторяющиеся совпадения, например. если yeet.d
каким-то образом содержится...
JET_FULE = /steal/beams
SHIA_LEBEOUF = /just/do/it
NEVER_GONNA = /give/you/up
AGAIN = /just/do/it
... будет две строки /just/do/it
, выведенные awk
.
Самый быстрый способ обойти это было бы передать |
в head -1
, но способ лучше состоял бы в том, чтобы сообщить awk
в exit
после того, как было сказано print
...
_string='/just/do/it'
_path='yeet.d'
awk -v _s = "${_string}" '$3 == _s {print $3; exit}' "${_path}"
... хотя теперь предполагается, что требуется только первое совпадение, получение n
й возможно, хотя в настоящее время выходит за рамки вопроса на момент последнего чтения.
Для путешествиеawk
в первом столбце при печати третьего столбца и выходе после первого совпадения может выглядеть...
_string='SHIA_LEBEOUF'
_path='yeet.d'
awk -v _s = "${_string}" '$1 == _s {print $3; exit}' "${_path}"
...и обобщать еще больше...
_string='^SHIA_LEBEOUF '
_path='yeet.d'
awk -v _s = "${_string}" '$0 ~ _s {print $3; exit}' "${_path}"
... потому что awk
регулярные выражения полностью получает, в основном.
Спасибо за отзыв @isakbob, я обновил свой ответ, чтобы, надеюсь, показать вам, что awk
— это то, на что стоит обратить внимание. Доступен целый язык сценарий, поэтому по мере роста проектов можно создавать повторно используемые биты... и это даже не касается того, насколько быстрее можно работать, внедрив awk
в рабочий процесс... Дайте нам знать, задав вопрос awk
, если да застряли на каком-то крайнем случае, возможно, отметьте меня, если хотите, так как иногда бывает трудно найти актуальную документацию по таким вещам.
Так что это абсолютно отличный способ ответить на вопрос, поэтому +1. Однако в моем контексте я действительно знаю только левую сторону (SHIA_LEBEOUF) и хочу получить правую сторону. Ответ @flappix содержит более общий способ.