Во-первых, отказ от ответственности.:Пожалуйста, не анализируйте вывод find
.Приведенный ниже код предназначен только для иллюстрации того, как включить подстановку команд в сценарий Awk таким образом, чтобы команды могли воздействовать на фрагменты ввода Awk.
Чтобы на самом деле выполнить подсчет строк(wc -l
)в каждом файле, найденном с помощью find
(, что является примером варианта использования ), просто используйте:
find. -type f -name '*txt' -exec wc -l {} +
Тем не менее, чтобы ответить на ваши вопросы,:
Чтобы ответить на ваш вопрос 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
Чтобы избежать печати имени файла 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: 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
, вся строка ввода, которая (для простого поиска выше )только имени файла.
Итак, все вышеперечисленное будет печатать только имя файла (ну, технически, всю строку ).
Простое создание каталога не должно быть проблемой. (Имейте в виду, что вам потребуется root ).
mkdir -p -m 755 /usr/local/bin
И добавить это к $PATH
, в~/.profile
PATH=$PATH:/usr/local/bin
Примечания редактора:
Протестировано на OpenWrt 18.06.4.
Разрешения изменены на 755, которые используются по умолчанию в Ubuntu согласно:
$ stat -c '%a %A %n' /usr/local/bin /usr/local /usr
755 drwxr-xr-x /usr/local/bin
755 drwxr-xr-x /usr/local
755 drwxr-xr-x /usr