Как извлечь определенные данные из строки

Задача

Я искал решение в Bash, которое может извлечь конкретную информацию после указанной строки.

Пример

Например (из acpi):

Battery 0: Discharging, 37%, 01:33:20 remaining

Как извлечь процент после выписки? В этом случае это будет 37% ...

Заметки

Я ищу простое решение, которое не требует набора командных аргументов.

7
задан 6 January 2018 в 09:41

5 ответов

Я не уверен, что вы имеете в виду, говоря «решение в bash», но awk может сделать эту работу:

awk -F", " '{print$2}'
  • -F", " - выберите запятую, а затем пробел в качестве разделителя F, это разбивает строку примера на три столбца, где второй - 37%
  • '{print$2}' - выведите второй столбец

Или как насчет sed?

sed -E 's/.* ([0-9]+%).*/\1/'
9
ответ дан 6 January 2018 в 09:41

Вот некоторые из них:

$ acpi | grep -oP '\d+%'
99%
$ acpi | awk -F',' '{print $2}'
 99%
$ acpi | perl -pe 's/.*?(\d+%).*/$1/'
99%
12
ответ дан 6 January 2018 в 09:41

Я искал решение в bash, которое может извлечь конкретную информацию после указанной строки.

После заданной строки? Ни один из двух ранее опубликованных ответов не сделал именно этого (поскольку захват текста после строки - не лучший способ получить информацию, которую, как вы сказали, вы хотели получить в своем примере).

Вот несколько способов получить текст после строки. Я использовал ваш пример, хотя оба ответа Десерта и Тердона демонстрируют более подходящие подходы к этому конкретному случаю.

Используйте \K из Perl, например, в grep с -P (разрешить регулярное выражение Perl) и -o (только совпадение):

grep -Po 'string\Kdesired'

Где string - выражение соответствует тому, что находится перед тем, что вы хотите, и desired - это выражение, совпадающее с тем, что вы хотите вывести. Это полезно, когда требуемый шаблон встречается в другом месте файла / строки (например, это число, а файл / строка содержит другие числа). В вашем примере это может быть что-то вроде:

$ acpi | grep -Po 'ing, \K[^,]+'
79%

[^,]+ означает некоторые символы, которые не являются запятой, поэтому это может захватывать текст до запятой. Мы также могли бы использовать ..., чтобы получить любые три символа, но, как указано в комментарии PerlDuck , вполне возможно, что шаблон, который вы здесь хотите, будет больше или меньше 3 символов.

В sed вы можете использовать группы захвата с ( и ):

sed -r 's/.*string(desired).*/\1/' 

, где \1 - это то, что было сохранено с ( ). Для вашего примера:

$ acpi | sed -r 's/.*ing, ([^,]+).*/\1/'
89%

Вот способ сделать это только с помощью Bash на вашем примере

$ output=$(acpi); string="${output#*ing, *}"; desired="${string%,*}"; echo "$desired"
96%

${var#string*} обрезает var до string (включительно) и ${var%string*} обрезает var после string (включительно).

1140 Это далеко не полный список. Есть много способов сделать это:)

7
ответ дан 6 January 2018 в 09:41

Решение для bash, как и было запрошено, без неуклюжих акизмов или оскорблений:

my_battery=( $(acpi) ); echo ${my_battery[3]}

Использует подстановку команды, создает массив вывода команды и отображает 4-й элемент массива.

Это работает с выходом acpi, который, по-видимому, всегда имеет процент батареи в качестве 4-го параметра. Если вы хотите найти элемент массива после «Разряда», вы не получите результат, если acpi сообщит вам «Батарея 0: Полное, 100%».

6
ответ дан 6 January 2018 в 09:41

Вы также можете использовать извлечение подстроки с расширением параметра

input=$(acpi)
expr "${input#*,[[:space:]]}" : '\([^,]*\)'
3
ответ дан 6 January 2018 в 09:41

Другие вопросы по тегам:

Похожие вопросы: