Предположим, что строка такая:

foo bar ENV['PGHOST'] another bar

Я хотел бы получить значение PGHOST в квадратные скобки рядом с ENV . Я предполагаю, что у линии есть только один такой случай. Итак, это: foo bar ENV['PGHOST'] another bar ENV['FOO'] and foo не является входом.

Тем не менее, строка может прийти с " вместо ' , как это:

foo bar ENV["PGHOST"] another bar

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

Мало того, фактическое значение может содержать двойные или одинарные кавычки. Если он заключен в одинарные кавычки, то он может содержать двойные кавычки. Если он заключен в двойные кавычки, то он может содержать одинарную кавычку. Итак, эти две строки являются допустимыми ожидаемыми данными:

foo bar ENV["PGH'OST"] another bar
foo bar ENV['PGH"OST'] another bar

Если я получу строки, подобные приведенным выше, результатом должны быть PGH'OST и PGH"OST соответственно.

Я знаю, как получить значение, если оно не содержит кавычек. Вот как я это делаю:

SED_COMMAND="s/^.*ENV\[['\"]\([^'\"]*\)['\"]\].*$/\1/"
echo $input | sed ${SED_COMMAND}

Таким образом, вышеприведенное прекрасно работает для input , foo bar ENV['PGHOST'] another bar или foo bar ENV["PGHOST"] another bar .

Но он не работает для foo bar ENV['PG"HOST'] another bar , ни для другого бара foo bar ENV["PG'HOST"] another bar .

Любая помощь приветствуется. Обратите внимание, что мне не нужно решать проблему с помощью sed . Любое другое предложение является приемлемым.

Обновление Обратите внимание, что я мог бы иметь такие данные:

foo bar ENV['PGHOST'] another bar "what a world" I 'live' in
foo bar ENV["PGHOST"] another bar "what a world" I 'live' in

т.е. двойные и / или одинарные кавычки могут существовать в частях ввода, которые находятся вне ключа ENV я хочу извлечь.

Обновить Другой пример правильного ввода:

foo bar ENV['PGHOST'] another bar in NEW['YORK'] to visit

это может быть действительный вход. Мне нужно получить PGHOST .

И это тоже верно:

foo bar ENV["PGH'OST"] another bar ["baz"]

который должен вернуть PGH'OST .

3 ответа3

1

Следующий более осмотрительный скрипт Bash сначала удаляет символ после первого появления ENV [и все, что перед ним, а затем удаляет символ до первого появления], и все после него. Скажите, пожалуйста, если у вас есть другие случаи, которые мешают работать как задумано.

x="foo bar ENV['PGHOST'] another bar in NEW['YORK'] to visit"; 
x=${x#*ENV[?}; x=${x%%?]*}; echo $x

Следующая версия будет читать из файла с именем 'input' и записывать результат в файл с именем 'output'.

cd ~/Desktop; 
while IFS= read -r x; 
do x=${x#*ENV[?}; echo ${x%%?]*} >> output;  
done < input 

Если «вход» содержит:

foo bar ENV['PGHOST'] another bar
foo bar ENV["PGHOST"] another bar
foo bar ENV["PGH'OST"] another bar
foo bar ENV['PGH"OST'] another bar
foo bar ENV['PGHOST'] another bar "what a world" I 'live' in
foo bar ENV["PGHOST"] another bar "what a world" I 'live' in
foo bar ENV['PGHOST'] another bar in NEW['YORK'] to visit
foo bar ENV["PGH'OST"] another bar ["baz"]

тогда в output будет записано следующее:

PGHOST
PGHOST
PGH'OST
PGH"OST
PGHOST
PGHOST
PGHOST
PGH'OST
1

Следующий скрипт Bash должен удалить:

1 - все до и включая первый [плюс один символ после него

2 - первый] и все после него плюс одна глава перед ним.

x="foo bar ENV['PGHOST'] another bar"; x=${x#*[?}; x=${x%%?]*}; echo $x 

Первая попытка не отображалась, как ожидалось, пока я не отступил в 4 пробела.

Теперь изменено, чтобы удалить все после первого].

Я думаю, что это должно работать для всех ваших существующих дел, но вы можете добавить больше дел.

0
$ SED_COMMAND="s/^.*ENV\[\(.\)\(.*\)\1\].*$/\2/"

$ cat input
foo bar ENV['PGHOST'] another bar
foo bar ENV['PGHO"ST'] another bar
foo bar ENV["PGHO'ST"] another bar
foo bar ENV["PGHOST"] another bar

foo bar ENV['PGHOST'] another bar "what a world" I 'live' in
foo bar ENV["PGHOST"] another bar "what a world" I 'live' in

foo bar ENV['PGHOST'] another bar in NEW['YORK'] to visit
foo bar ENV["PGH'OST"] another bar ["baz"]


$ cat input | sed ${SED_COMMAND}
PGHOST
PGHO"ST
PGHO'ST
PGHOST

PGHOST
PGHOST

PGHOST'] another bar in NEW['YORK
PGH'OST"] another bar ["baz

Работает почти на все твои глупые глупости. За исключением двух последних, вам понадобится Perl для этого, потому что у sed нет нежадных возможностей, или избавьтесь от кавычек в квадратных скобках и используйте [:alpha:] или \w. Все, что я изменил, - это предположил, что кавычка ('или "), которая отделяет захваченное слово, следует непосредственно за открывающей квадратной скобкой [, затем захватила кавычку с помощью ., Чтобы поймать' или" и использовала ее в качестве окончания разделитель для обратной ссылки \2. Затем, используя sed, как вы сделали, перевели всю строку только в ту часть, которую хотите захватить.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .