подстановка команд внутри awk

Описание проблемы

Это неправильный способ установки цветов для ls . ls использует цвета терминала так же, как и приглашение. Когда dev окрашен в коричневый цвет ls , это происходит примерно так:

\[\033[0;33\]dev\[\033[0m\]

И цвет терминала снова переключается на обычный цвет ( \ [\ 033 [0m \] ). С этого момента для отображения текста используется обычный цвет, пока Documents не переключится на коричневый, а затем снова на обычный.

По сути, это плохая идея - иметь подсказку, которая оставляет включенным цвет терминала:

PS1='${debian_chroot:+($debian_chroot)}\[\033[00;37m\]\u@\h:\w\$\[\033[01;33m\] '

Вместо этого вы должны всегда переключать цвет обратно на обычный:

PS1='${debian_chroot:+($debian_chroot)}\[\033[00;37m\]\u@\h:\w\$\[\033[0m\] '

А затем использовать ] LS_COLORS переменная среды для изменения способа ls печати цветов.


Hack

ls имеет псевдоним:

alias ls='ls --color'

В большинстве современных дистрибутивов Linux. Удаление этого псевдонима - один из способов заставить вашу хакерскую подсказку работать с ls . Но это не лучшее решение, и вы, вероятно, столкнетесь с проблемами с другими программами.


Правильное решение

Если вы действительно хотите изменить цвет текста по умолчанию в терминале, вы должны настроить его в самом эмуляторе терминала. Практически все эмуляторы терминала ( gnome-terminal , xfce-terminal , kterm ) имеют раздел конфигурации, в котором можно установить стандартный (обычный) цвет.

В вариантах xterm и rxvt цвет по умолчанию может быть установлен в ~ / .Xresources .

3
28.07.2017, 00:03
2 ответа

Во-первых, отказ от ответственности.:Пожалуйста, не анализируйте вывод find.Приведенный ниже код предназначен только для иллюстрации того, как включить подстановку команд в сценарий Awk таким образом, чтобы команды могли воздействовать на фрагменты ввода Awk.

Чтобы на самом деле выполнить подсчет строк(wc -l)в каждом файле, найденном с помощью find(, что является примером варианта использования ), просто используйте:

 find. -type f -name '*txt' -exec wc -l {} +

Тем не менее, чтобы ответить на ваши вопросы,:

Q1

Чтобы ответить на ваш вопрос 1:

Q1: is there a way to perform command substitution inside awk?

Конечно есть способ, отman awk:

command | getline [var] Run command piping the output either into $0 or var, as above, and RT.

Итак (Смотрите цитирование!!):

find. | awk '/txt$/{"wc -l <\"" $NF "\"|cut -f1" | getline(nl); print(nl)}'

Обратите внимание, что построенная строка и, следовательно, выполняемая команда — это

wc -l <file

Чтобы избежать печати имени файла wc.

Ну, я избегал нужного файла "закрыть" для этой команды (безопасным для пары файлов, но технически некорректным ). Вам действительно нужно сделать:

find. | awk '/txt$/{
                       comm="wc -l <\"" $NF "\" | cut -f1"
                       comm | getline nl;
                       close (comm);
                       print nl 
                    }'

Это работает и для старых версий awk.
Помните, что следует избегать печати точки .вместе с find., что приведет к сбою кода, поскольку точка является каталогом, и wc не может его использовать.

Либо избегайте использования точечных значений:

find. | awk '/txt$/ && $NF!="." {  comm="wc -l <\"" $NF "\" | cut -f1"
                                    comm | getline nl;
                                    close (comm);
                                    print nl 
                                 }'

Вы можете преобразовать это в один -лайнер, но это будет выглядеть довольно уродливо, думает Ми.

Q2

Что касается вашего второго вопроса:

Q2: why is the first incantation above silently failing and is simply printing the filenames instead?

Поскольку awk неправильно анализирует команды оболочки. Команда понимается как:

nl = $(wc -l $NF)
nl --> variable
$ --> pointer to a field
wc --> variable (that has zero value here)
-  --> minus sign
l  --> variable (that has a null string)
$  --> Pointer to a field
NF --> Last field

Затем l $NFстановится конкатенацией нуля и текста внутри поля las (имени файла ). Расширение такого текста как числовой переменной представляет собой числовое значение 0

.

Для awk это становится:

nl = $( wc -l $NF)
nl = $ ( 0 - 0 )

Который становится просто $0, вся строка ввода, которая (для простого поиска выше )только имени файла.

Итак, все вышеперечисленное будет печатать только имя файла (ну, технически, всю строку ).

4
27.01.2020, 21:15

Используйте "weak quotes", а не 'strong quotes', чтобы расширение подоболочки происходило внутри скрипта awk, но это в вашем примере не будет особенно полезной реализацией. Это также выглядит фантастически безобразно:

$ awk "END { print \"$(echo hello)\"} " < /dev/null
hello
1
27.01.2020, 21:15

Теги

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