Подстановка sed переменными bash

Пытаясь изменить значения в текстовом файле, используя sed в bash-скрипте со строкой,

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

Это будет в цикле. Не уверен, почему это не работает. Какие-либо предложения?

6 ответов

Решение

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

$ # enclose 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 relevant portion
$ # and prevent accidental expansion for !, backticks, etc
$ sed 's/draw('"$prev_number"';n_)/draw('"$number"';n_)/g' file.txt > tmp

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


Дальнейшее чтение:

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

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

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

sed "s/draw($prev_number;n_)/draw($number;n_)/g" 

это будет работать?

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

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

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

host_var=`hostname`

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

Другой вариант с использованием:

      SED_EXPR="$(printf -- 's/draw(%s;n_)/draw(%s;n_)/g' $prev_number $number)"

sed "${SED_EXPR}" file.txt

или в одну строку:

      sed "$(printf -- 's/draw(%s;n_)/draw(%s;n_)/g' $prev_number $number)" file.txt

С использованиемprintfчтобы построить выражение замены, должно быть безопасно от всевозможных странных вещей, поэтому мне нравится этот вариант.

I needed to input github tags from my release within github actions. So that on release it will automatically package up and push code to artifactory.

Here is how I did it. :)

        - 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

Retrospectively I wish I did this in python with tests. However it was fun todo some bash.

Другие вопросы по тегам