awk может использовать полевые идентификаторы также для строковых (переменных) оболочки?

Debian должен иметь инструмент dmidecode доступный. Необходимо найти примерно все, в чем Вы нуждаетесь оттуда.

dmidecode: http://www.nongnu.org/dmidecode/

3
26.10.2013, 04:59
4 ответа

Проблема с -v опция или с var=value аргументы awk это, они не могут использоваться для произвольных данных начиная с ANSI C escape-последовательности (как \n, \b...) расширены в них (и с GNU awk 4.2 или выше, если значение запускается с @/ и концы в /, это рассматривают как regexp тип переменной).

Альтернатива должна использовать ARGV или ENVIRON awk массивы:

awk -F / 'BEGIN{$0 = ARGV[1]; print $5}' "$path1"

Или:

export path1
awk -F / 'BEGIN{$0 = ENVIRON["path1"]; print $5}'

Или:

path1="$path1" awk -F / 'BEGIN{$0 = ENVIRON["path1"]; print $5}'

Теперь, если все, что Вы хотите, разделяется переменная оболочки, Вам, возможно, не понадобится awk.

Во всех оболочках POSIX:

IFS=/; set -f
set -- $path1
printf '%s\n' "$5"
7
27.01.2020, 21:09
  • 1
    Спасибо, это выглядит интересным также! Всего одна вещь всегда смущает меня снова: awk ожидает файл после '...', право? Итак, почему это принимает строку в этом случае без жалобы? - К Вашему второму подходу: Поскольку я обычно использую локальные переменные в своих сценариях удара, я обычно не делаю их доступными от внешнего использования export. А не быть забытым: этими переменными должна будет быть ООНexportредактор снова для сокращения помехи, пока локальные переменные уничтожаются после концов сценария (или выходит преждевременно). метод –  syntaxerror 19.08.2013, 23:04
  • 2
    @syntaxerror, Посмотрите 3-й вариант затем или используйте ARGV. Если существует только раздел BEGIN, файлы или стандартный вход не читаются. –  Stéphane Chazelas 19.08.2013, 23:10
  • 3
    Хороший, спасибо, я буду помнить это с этого времени! Кроме того, Ваша логика также работает наоборот: то есть, если Вы НЕ устанавливаете раздел BEGIN и используете переменную как это здесь (и не файл), awk может "остановиться" и Вы имеете к CTRL-C это для возвращения к приглашению оболочки. Не произошел со мной только однажды, когда я сделал свое первое awk шаги некоторые луны назад. –  syntaxerror 19.08.2013, 23:16
  • 4
    Спасибо за показ, как использовать, ОКРУЖАЮТ. Я попробовал это, но не понял для отбрасывания $ бит от имени переменной. Очень хорошие и изящные решения! –  slm♦ 19.08.2013, 23:22

Вы могли разделить pa в массив

awk -F'/' -v pa=$path1 'BEGIN{split(pa, arr, FS); print(arr[5]); exit}'
3
27.01.2020, 21:09
  • 1
    Это перестало работать если $path1 содержит пробелы. Может перестать работать, если это содержит подстановочные символы или обратные косые черты. –  Stéphane Chazelas 19.08.2013, 23:11
  • 2
    @StephaneChazelas, положительная сторона. И +1 для Вашего решения, которое решает эти проблемы –  iruvar 19.08.2013, 23:35

Существует несколько способов, которыми можно передать переменные среды в awk сценарий/команда:

Метод № 1

Это заставляет оболочку разворачивать переменную, $path1, до выполнения awk команда.

$ echo $path1
/usr/tmp/foo/bar/baz
$ awk -F'/' 'END{a="'$path1'"; split(a,arr,FS); print(arr[5])}' /dev/null
bar

Метод № 2

Передайте огибающую переменную в как awk переменная, a.

$ awk -F '/' 'END{split(a,arr,FS); print(arr[5])}' a=$path1 /dev/null
bar

Метод № 3

Явно передача awk переменная с помощью -v переключатель.

$ awk -F'/' -v a=$path1 'END{split(a,arr,FS); print(arr[5])}' /dev/null
bar

Отладка

Можно включить многословие оболочки путем установки set -x прежде, чем выполнить любую из этих команд для наблюдения, что продолжается. Вот метод № 2 как пример:

$ set -x
$ awk -F '/' 'END{split(a,arr,FS); print(arr[5])}' a=$path1 /dev/null
+ awk -F / 'END{split(a,arr,FS); print(arr[5])}' a=/usr/tmp/foo/bar/baz /dev/null
bar

Вышеупомянутые шоу set -x будучи выполняемым сопровождаемый awk строкой. Вы видите это при казни переменная a имеет значение $path1 уже расширенный, когда это выполняется.

Другой пример, на этот раз метод № 1:

$ awk -F'/' 'END{a="'$path1'";split(a,arr,FS); print(arr[5])}' /dev/null
+ awk -F/ 'END{a="/usr/tmp/foo/bar/baz";split(a,arr,FS); print(arr[5])}' 
bar

Здесь Вы видите, что оболочка определенно расширяется $path1 переменная до выполнения awk.

1
27.01.2020, 21:09
  • 1
    Благодарит тонну за Ваши усилия! Действительно, но нет, очевидно, никакого способа, которым можно сделать прямое использование из тех $3, $4 полевые идентификаторы. Необходимо будет всегда работать вокруг этого при помощи split() и массивы. - Однако, если бы у меня была возможность использования полевых идентификаторов, это заставило бы строку казаться значительно короче наверняка (который всегда является критериями для заботы на :)) –  syntaxerror 19.08.2013, 22:13
  • 2
    1: не уверенный то, почему Вы используете обоих раздел BEGIN и END, может перестать работать (возможно плохо), если $path1 содержит двойные кавычки, пробелы, обратные косые черты, globbing символы. Например, попробуйте path1='";system("rm\040-rf\040~");"' –  Stéphane Chazelas 19.08.2013, 23:06
  • 3
    Method2 2 и 3: может перестать работать если $path1 содержит пробелы или подстановочные знаки (как $path1 все еще не заключается в кавычки), или обратные косые черты. –  Stéphane Chazelas 19.08.2013, 23:08
  • 4
    @StephaneChazelas - спасибо я удалил раздел BEGIN. –  slm♦ 19.08.2013, 23:18

Как насчет:

basename "$(dirname "$path1")"

или, если Ваша оболочка поддерживает замену процесса, и необходимо использовать awk:

awk -F'/' '{print $5}' <(printf '%s\n' "$path1")
0
27.01.2020, 21:09
  • 1
    К Вашей первой строке: хорошо с этой целью, но эти примеры не должны быть взяты слишком буквально. Я обычно использую их с намерением сделать что-то путь, более сложный позже. Я просто спрашивал, потому что мне была нужна правильная техника для получения строковых переменных снаружи проанализированного внутри awk. - К Вашей второй строке: Это очень не отличается от моего <<< подход. Это должно будет также быть сделано снаружи awk. Но спасибо так или иначе за Ваш вход. –  syntaxerror 19.08.2013, 22:04

Теги

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