замена sed переменными Bash

Я пытаюсь изменить значения в текстовом файле, используя sed в сценарии Bash со строкой,

sed 's/draw($prev_number;n_)/draw($number;n_)/g' file.txt > tmp

Это будет в цикле for. Почему это не работает?


person csta    schedule 06.10.2011    source источник


Ответы (5)


Переменные внутри ' не заменяются в Bash. Чтобы получить подстановку строк (или интерполяцию, если вы знакомы с Perl), вам нужно изменить ее, чтобы использовать двойные кавычки " вместо одинарных:

$ # Enclose the entire expression in double quotes
$ sed "s/draw($prev_number;n_)/draw($number;n_)/g" file.txt > tmp

$ # Or, concatenate strings with only variables inside double quotes
$ # This would restrict expansion to the relevant portion
$ # and prevent accidental expansion for !, backticks, etc.
$ sed 's/draw('"$prev_number"';n_)/draw('"$number"';n_)/g' file.txt > tmp

$ # A variable cannot contain arbitrary characters
$ # See link in the further reading section for details
$ a='foo
bar'
$ echo 'baz' | sed 's/baz/'"$a"'/g'
sed: -e expression #1, char 9: unterminated `s' command


Дополнительная литература:

person k.parnell    schedule 06.10.2011
comment
Можно также упомянуть, что если переменная содержит косые черты, вам нужно использовать другой разделитель, который не встречается в строке (или экранировать обратную косую черту при каждом появлении разделителя). Косая черта используется по умолчанию для s, но вы можете использовать любой знак пунктуации; sed "s%draw($prev_number;n_)%draw($number;n_)%g" file.txt или s#from#to#g или s_from_to_g и т. д. - person tripleee; 25.06.2015
comment
это не работает, если переменная содержит новые строки (\n) - person dentex; 02.04.2018
comment
но однажды он сбежал (для моих случаев использования) также косая черта: changelogEscaped=$(sed -e 's%\/%\\/%g; $!a\'$'\n''\\n' <<<"$changelog" | tr -d '\n') Спасибо за ссылку выше. - person dentex; 02.04.2018

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

sed "s/draw($prev_number;n_)/draw($number;n_)/g" file.txt > tmp

Вы также можете заставить его работать с eval, но не делайте этого!!

person Paul Creasey    schedule 06.10.2011
comment
Спасибо, это сработало. Не могли бы вы пояснить, что вы имеете в виду под расширением? Моя интуиция подсказывает мне, что это должно быть что-то вроде подстановки переменной. Также почему бы не использовать eval? - person csta; 07.10.2011

Это может помочь:

sed "s/draw($prev_number;n_)/draw($number;n_)/g" 
person Kent    schedule 06.10.2011

Вы можете использовать переменные, как показано ниже. Как и здесь, я хотел заменить hostname, т.е. системную переменную в файле. Я ищу строку look.me и заменяю всю эту строку на look.me=<system_name>

sed -i "s/.*look.me.*/look.me=`hostname`/"

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

host_var=`имя хоста`

sed -i "s/.*look.me.*/look.me=$host_var/"


Входной файл:

look.me=demonic

Вывод файла (при условии, что имя моей системы prod-cfm-frontend-1-usa-central-1):

look.me=prod-cfm-frontend-1-usa-central-1
person daemonsl    schedule 16.06.2016

Мне нужно было ввести теги github из моего выпуска в действиях github. Так что при выпуске он автоматически упаковывается и проталкивает код в артефакт.

Вот как я это сделал. :)

  - name: Invoke build
    run: |
      # Gets the Tag number from the release
      TAGNUMBER=$(echo $GITHUB_REF | cut -d / -f 3)
      
      # Setups a string to be used by sed
      FINDANDREPLACE='s/${GITHUBACTIONSTAG}/'$(echo $TAGNUMBER)/
      
      # Updates the setup.cfg file within version number
      sed -i $FINDANDREPLACE setup.cfg
      
      # Installs prerequisites and pushes 
      pip install -r requirements-dev.txt
      invoke build

Ретроспективно я хотел бы сделать это на питоне с тестами. Тем не менее, было весело немного поболтать.

person James Green    schedule 16.03.2021