2017-02-10 2 views
-2

У меня есть эта строка:как напечатать последнюю часть строки в сценарии оболочки

102:20620453:d=2017021012:UGRD:10 m above ground:15 hour fcst::lon=79.500000,lat=9.000000,val=-5.35 

Теперь я хочу просто напечатать значение -5.35 от этой линии, и больше ничего.

Я также хочу, чтобы эта команда могла извлекать -7.04 из этой строки и ничего больше.

102:20620453:d=2017021012:UGRD:10 m above ground:15 hour fcst::lon=280.500000,lat=11.000000,val=-7.04 

Я прочитал другие вопросы переполнения стека, и они, похоже, не дошли до того, что я искал. Я заметил, что они сделали вас awk или sed. Какие типы вещей я должен сделать, чтобы иметь возможность извлекать только часть вышеуказанных строк после val =?

+0

ли 'val' абсолютно положительно гарантированно будет последним в каждой строке - не только для текущей версии строки журнала, но и для всех будущих версий? Лично я был бы осторожен в принятии такого предположения. –

+1

BTW - вы обрабатываете одну строку за раз или весь файл в пути? Это имеет большое значение в производительности: вам лучше использовать 'awk' для больших потоков, тогда как если вы идете по очереди за раз, использование встроенных настроек bash позволит сэкономить (значительную) стоимость запуска внешнего процесса. (То есть: ответ anubhava намного медленнее, чем мой, если вы просто запускаете одну копию awk на строку ведения журнала, но гораздо быстрее взять awk от anubhava и дать ему 20 МБ журналов, чтобы разобрать все сразу, чем использовать bash-встроенная строковая манипуляция в цикле). –

ответ

2

Там нет необходимости awk, sed, или любой другой внешний инструмент: Баш имеет свой собственный встроенный поддержки регулярных выражений, через оператора =~ до [[ ]] и массив BASH_REMATCH (заполненный согласованным содержимым).

val_re='[, ]val=([^ ]+)' 
line='102:20620453:d=2017021012:UGRD:10 m above ground:15 hour fcst::lon=79.500000,lat=9.000000,val=-5.35' 
[[ $line =~ $val_re ]] && echo "${BASH_REMATCH[1]}" 

Тем не менее, если вы действительно хотите удалить все, вплоть до строки val= (и, таким образом, чтобы иметь свой код перерыв, если другие значения были добавлены в формат в будущем), вы также можете сделать так, как это:

val=${line##*val=} # assign everything from $line after the last instance of "val=" to val 

синтаксис здесь parameter expansion. Смотрите также BashFAQ #100: How do I do string manipulations in bash?

1

Вы можете использовать AWK с разделителем полей в = и печать последнего поля:

awk -F'=' '{print $NF}' <<< "$str" 

-5.35 
0

это будет искать строку Val = с конца и дать что-либо после этого

str='102:20620453:d=2017021012:UGRD:10 m above ground:15 hour fcst::lon=79.500000,lat=9.000000,val=-5.35' 

echo "$str" | grep -Po '(?<=val=).*' 

ответ работает на GNU Grep только

+1

... полный список функций * гарантированный *, который будет доступен в 'grep', приведен в http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html. Не то, чтобы написать ответ StackOverflow, который зависит от расширений, не так, но его следует вызывать, когда ответ работает только на GNU grep, современный BSD grep или на другую конкретную реализацию. (И фактически даже с GNU grep поддержка '-P' зависит от флагов времени компиляции, которые могут быть включены только в системах с libpcre). –

+1

... re: 'echo $ str', см. [BashPitfalls # 14] (http://mywiki.wooledge.org/BashPitfalls#echo_.24foo) или запустите свой код через http://shellcheck.net/ и перейдите по ссылке в предупреждении на [SC2086] (https://github.com/koalaman/shellcheck/wiki/SC2086). –

+0

Вы исправили проблему с кавычками, но ваш ответ по-прежнему не упоминает, что использование '-P' требует _GNU_' grep'. Привязка регулярного выражения в '' ... "', а не '' ... '' не рекомендуется, если вы не намерены вставлять ссылки на shell-переменные. '[^ $]' здесь не имеет смысла (он соответствует любому char. _except_ ('^') a _literal_ '$') - вы, вероятно, имели в виду просто '.'. В заключение. пожалуйста [правильно отформатируйте свой код] (http://meta.stackexchange.com/a/22189/248777). – mklement0

Смежные вопросы