Как создать переменную оболочки с пробелами в скрипте AWK - PullRequest
0 голосов
/ 30 ноября 2018

У меня есть путь "file1 Nov 2018.txt", хранящийся в переменной "var".Затем я использую эту переменную оболочки внутри скрипта awk для генерации другого скрипта (это небольшой пример).Проблема в том, что путь и имя файла имеют пробелы, и даже я помещаю переменную между двойными кавычками "", а внутри awk, которую я ставлю между одинарными кавычками, '' тоже не работает.Я получаю сообщение об ошибке «Нет такого файла или каталога»

Как обработать этот путь, который имеет пробелы?

Сценарий выглядит так:

var="/mydrive/d/data 2018/Documents Nov/file1 Nov 2018.txt"
z=$(awk -v a="$var" 'BEGIN{str = "cat " 'a' ; print str}')
eval "$z"

Я получаю этиошибки:

$ eval "$z"
cat: /mydrive/d/data: No such file or directory
cat: 2018/Documents: No such file or directory
cat: Nov/file1: No such file or directory
cat: Nov: No such file or directory
cat: 2018.txt: No such file or directory

Спасибо за любую помощь.

Ответы [ 4 ]

0 голосов
/ 30 ноября 2018

С помощью bash's printf %q "$var" вы можете корректно экранировать любую строку для последующего использования в eval - даже переносы строк будут обрабатываться правильно.Однако результирующая строка может содержать специальные символы, такие как \, которые можно интерпретировать как awk при назначении переменных с помощью awk -v var="$var".Поэтому лучше передать переменную через stdin:

path='/path/with spaces/and/special/symbols/like/*/?/\/...'
cmd=$(printf %q "$path" | awk '{print "cat "$0}')
eval "$cmd"

В этом примере сгенерированная команда $cmd равна

cat /path/with\ spaces/and/special/symbols/like/\*/\?/\\/...
0 голосов
/ 30 ноября 2018

Экранирующая одиночная кавычка пригодится здесь.Обратите внимание, что 047 - это восьмеричное значение для символа ASCII ', а awk позволяет использовать \nnn в строке для включения любого символа, использующего его восьмеричное значение.

$ cat 'foo bar.txt'
a  b c
1  2 3

$ var="foo bar.txt"

$ echo "$var"
foo bar.txt

$ z=$(awk -v a="$var" 'BEGIN{print "cat \047" a "\047"}')

$ eval "$z"
a  b c
1  2 3

Возможно, это немногоприятнее с printf:

$ awk -v a="$var" 'BEGIN{ printf "cat \047%s\047\n", a }'
cat 'foo bar.txt'

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

Этого можно избежать, поместив программу awk в ее собственный файл:

$ cat a.awk
BEGIN { printf "cat '%s'\n", a }

$ awk -v a="$var" -f a.awk
cat 'foo bar.txt'
0 голосов
/ 30 ноября 2018
$ cat > path\ to/test
foo
$ z=$(awk -v a="$var" 'BEGIN{gsub(/ /,"\\ ",a); str = "cat " a ; print str}')   
$ echo "$z"
cat path\ to/test
$ eval "$z"
foo

Ключ (в этом решении): gsub(/ /,"\\ ",a) т.е.экранирование с \ (\\ из-за awk).

0 голосов
/ 30 ноября 2018

удалите одинарные кавычки вокруг a и добавьте вместо них экранированные двойные кавычки.

$ echo success > "a b"
$ var="a b"; z=$(awk -v a="$var" 'BEGIN{print "cat \"" a "\""}');
$ eval "${z}"

success

однако, скорее всего, вы выполняете какую-то задачу, излишне сложную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...