2016-03-27 4 views
1

У меня есть файл с этими аргументами и их значения таким способомКак передать цитируемые аргументы, но с пробелами в Linux

# parameters.txt 

VAR1 001 
VAR2 aaa 
VAR3 'Hello World' 

и другой файл для настройки, как этот

# example.conf 

VAR1 = 020 
VAR2 = kab 
VAR3 = '' 

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

while read p; do 
    VALUE=$(echo $p | awk '{print $2}') 
done < parameters.txt 

аргументы firsts выставляют правильные значения , но последний из них просто получает «Hello for the blank space», мой вопрос в том, как получить всю ценность Hello World?

+0

Двойное цитирование переменной должно исправить это. т. е. «$ p» –

+0

Как работает 'example.conf'? Вам нужен код, который может обрабатывать форматы _both_ - с или без '=' между ключом и значением? – mklement0

+0

@JacobH: Несмотря на то, что всегда полезно перекодировать ссылки на переменные в POSIX-подобном программировании (если вы специально не хотите разделить слово и глобусы), это не решит проблему. – mklement0

ответ

0

Если вы можете использовать bash, есть нет необходимости использовать awk: read и shell parameter expansion не могут быть объединены, чтобы решить вашу проблему:

while read -r name rest; do 
    # Drop the '= ' part, if present. 
    [[ $rest == '= '* ]] && value=${rest:2} || value=$rest 
    # $value now contains the line's value, 
    # but *including* any enclosing ' chars, if any. 
    # Assuming that there are no *embedded* ' chars., you can remove them 
    # as follows: 
    value=${value//\'/} 
done < parameters.txt 

read по умолчанию также разбивает строку на поля пробелами, как awk, но в отличие от awk он имеет возможность назначить остаток линии к Название переменной, а именно последний один, если меньше переменных, чем полей найдены указаны;
read-r вариант, как правило, стоит указать, чтобы избежать неожиданной интерпретации символов \. на входе.


Как для попытки решения:

awk не знает о цитировании на входе - по умолчанию он разбивает вход на поля пробелами, независимо от кавычек.
Таким образом, строка, такая как 'Hello World', просто разбита на поля 'Hello и World'.

Однако в вашем случае вы можете разделить каждую входную линию на ее ключ и значение с помощью тщательно созданного значения FS (FS - это разделитель полей ввода, который также можно установить с помощью опции -F, а команда снова принимает bash, на этот раз для использования <(...), так называемой process substitution и $'...', ANSI C-quoted string):

while IFS= read -r value; do 
    # Work with $value... 
done < <(awk -F$'^[[:alnum:]]+ (=)?\'?|\'' '{ print $2 }' parameters.txt) 

Снова предположение, что значения не содержат встроенных' экземпляров.

Разделитель регулярное выражение $'^[[:alnum:]]+ (=)?\'?|\'' разбивает каждую строку так, чтобы $2, 2-е поле, содержит значение, раздели ограждающих ' символов., Если таковые имеются.


xargs является редким исключением среди стандартных утилит в том, что он делает понять одно- и строк в двойных кавычках (еще и без поддержки встроенных кавычек).

Таким образом, вы можете воспользоваться xargs 'способности неявно отогнать ограждающие кавычки, когда он передает аргументы в указанную команду, которая по умолчанию echo (опять-таки предполагает bash):

while read -r name rest; do 
    # Drop the '= ' part, if present. 
    [[ $rest == '= '* ]] && value=${rest:2} || value=$rest 
    # $value now contains the line's value, strippe of any enclosing 
    # single quotes by `xargs`. 
done < <(xargs -L1 < parameters.txt) 

xargs -L1 один процесс (1) (-L) одновременно и неявно вызывает echo со всеми токенами, найденными в каждой строке, с любыми закрывающими кавычками, удаленными из отдельных токенов.

+0

Мне нужно узнать, как именно работает этот код, но делает именно то, что я искал. Благодаря! –

+0

@AbdelP. С удовольствием; Я добавил дополнительную информацию и ссылки, которые могут быть полезны. – mklement0

+1

Я тоже очень благодарен за это @ mklement0 –

-1

По умолчанию разделитель полей в awk - это пробел. Таким образом, вы печатаете только первое слово в строке, переданной awk.

Вы можете указать разделитель полей в командной строке с -F [разделитель полей]

Например, установка разделитель полей запятая:

$ echo "Hello World" | awk -F, '{print $1}'  
Hello World 
+0

Да, но когда вы меняете разделитель полей, он выводит всю строку ** VAR3 'Hello World' ** –

+0

@AbdelP. '' Является просто примером (кроме того, что он должен быть '-F,', а не '-FS ', _option_' -F' переводится в _variable_ 'FS' внутри скрипта' awk') , но значение _single-character_ не может решить вашу проблему. – mklement0

Смежные вопросы