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

Проблема

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

Пример

Например (от запуска acpi):

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

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

Примечания

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

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

13 ответов

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

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

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

sed -E 's/.* ([0-9]+%).*/\1/'
9
ответ дан 22 May 2018 в 15:45
  • 1
    Этот ответ отлично работает, спасибо !!! – NerdOfCode 4 January 2018 в 21:16
  • 2
    Если бы вы могли объяснить пример awk, это было бы здорово. Я планировал просто возиться с ним, но объяснение было бы лучше. – NerdOfCode 4 January 2018 в 21:18
  • 3
    Фантастично, большое спасибо. – NerdOfCode 4 January 2018 в 21:22
  • 4
    Единственное, что я не понимаю, это скобки, необходимые в финальном заявлении - & gt; {} from - & gt; [F2] – NerdOfCode 4 January 2018 в 21:34
  • 5
    @NerdOfCode Это потому, что это оператор действия, см. PATTERNS AND ACTIONS в man awk. – dessert 4 January 2018 в 21:44

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

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

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

sed -E 's/.* ([0-9]+%).*/\1/'
9
ответ дан 17 July 2018 в 23:51

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

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

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

sed -E 's/.* ([0-9]+%).*/\1/'
9
ответ дан 24 July 2018 в 17:07

Вот несколько:

$ acpi | grep -oP '\d+%'
99%
$ acpi | awk -F',' '{print $2}'
 99%
$ acpi | perl -pe 's/.*?(\d+%).*/$1/'
99%
12
ответ дан 22 May 2018 в 15:45
Я искал решение в bash, которое может извлекать определенную информацию после указанной строки.

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

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

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

grep -Po 'string\Kdesired'

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

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

[^,]+ означает некоторые символы, которые не являются запятой, поэтому это может захватывать текст до запятой. Мы могли бы также использовать ... для получения любых трех символов, но, как указано в ответе десерта , возможно, шаблон, который вы хотите здесь, будет больше или меньше 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*} fims var до string (включительно) и ${var%string*} var после string (включительно).

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

7
ответ дан 22 May 2018 в 15:45
  • 1
    Ничего себе, это очень подробный ответ с большими объяснениями, спасибо, но я боюсь, что @dessert уже избил тебя до этого ... – NerdOfCode 4 January 2018 в 23:25
  • 2
    Соответствие трех символов (как в (...)) может быть неуместным, если процент меньше 10. Или 100. – PerlDuck 4 January 2018 в 23:33
  • 3
    @PerlDuck хорошая точка! Редактировал :) – Zanna 4 January 2018 в 23:40

Решение bash, как и было запрошено, без каких-либо неудобных awkisms или sedulous sedisms:

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

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

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

6
ответ дан 22 May 2018 в 15:45

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

input=$(acpi)
expr "${input#*,[[:space:]]}" : '\([^,]*\)'
3
ответ дан 22 May 2018 в 15:45

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

input=$(acpi) expr "${input#*,[[:space:]]}" : '\([^,]*\)'
3
ответ дан 17 July 2018 в 23:51

Вот несколько:

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

Решение bash, как и было запрошено, без каких-либо неудобных awkisms или sedulous sedisms:

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

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

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

6
ответ дан 17 July 2018 в 23:51

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

input=$(acpi) expr "${input#*,[[:space:]]}" : '\([^,]*\)'
3
ответ дан 24 July 2018 в 17:07

Вот несколько:

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

Решение bash, как и было запрошено, без каких-либо неудобных awkisms или sedulous sedisms:

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

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

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

6
ответ дан 24 July 2018 в 17:07
  • 1
    Ничего себе, это очень подробный ответ с большими объяснениями, спасибо, но я боюсь, что @dessert уже избил тебя до этого ... – NerdOfCode 4 January 2018 в 23:25
  • 2
    Соответствие трех символов (как в (...)) может быть неуместным, если процент меньше 10. Или 100. – PerlDuck 4 January 2018 в 23:33
  • 3
    @PerlDuck хорошая точка! Редактировал :) – Zanna 4 January 2018 в 23:40

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

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