Развернуть совпадающие строки в sed - PullRequest
1 голос
/ 14 апреля 2020

Можно ли раскрыть соответствующую строку в команде sed? Я хочу заменить имена переменных в файле их значениями, на данный момент это мой скрипт:

#!/bin/bash

echo "Running the build script..."
VAR1="2005648"
VAR2="7445aa"
SERVER_NAME=$(hostname)
TIMESTAMP=$(date +%m-%d-%Y)
sed -i "s/{[A-Z_][A-Z_]*}/$&/g" my_file.txt  #variable names in the file are written between { }

, и это снимок файла my_file.txt:

Building finished at {TIMESTAMP}
{VAR1}:{VAR2}
On: {SERVER_NAME}
current working directory: {PWD}

Но это не работает Вместо того, чтобы подставлять имя переменной в ее значение, она вставляет знак доллара прямо перед фигурной скобкой. Как мне решить эту проблему?

Ответы [ 3 ]

4 голосов
/ 14 апреля 2020

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

Измените файл шаблона на:

Building finished at ${TIMESTAMP}
${VAR1}:${VAR2}
On: ${SERVER_NAME}
current working directory: ${PWD}

И скрипт:

#!/bin/bash

echo "Running the build script..."
export VAR1="2005648"
export VAR2="7445aa"
export SERVER_NAME=$(hostname)
export TIMESTAMP=$(date +%m-%d-%Y)

# only replace the defined variables
envsubst '$VAR1 $VAR2 $SERVER_NAME $TIMESTAMP' < my_file.txt > newfile

# replace all environment variables ($USER, $HOME, $HOSTNAME, etc.)
#envsubst < my_file.txt > newfile.txt > newfile

Скрипт заменяет переменные окружения $VAR1, $VAR2, $SERVER_NAME и $TIMESTAMP в my_file.txt и сохраняет вывод в newfile. Вы можете видеть, что ${PWD} не заменяется, потому что я забыл добавить его в список.

Во втором примере с комментариями все переменные среды заменяются, а несуществующие переменные заменяются пустой строкой. .

В шаблоне можно использовать синтаксис $VARNAME или ${VARNAME}.

2 голосов
/ 14 апреля 2020

Я бы сделал это за один проход, используя awk, который поддерживает ENVIRON[], например, любой POSIX awk:

$ cat tst.sh
#!/bin/env bash

echo "Running the build script..."

VAR1=2005648 \
VAR2=7445aa \
SERVER_NAME=$(hostname) \
TIMESTAMP=$(date +%m-%d-%Y) \
awk '
{
    while ( match($0,/{[[:alnum:]_]+}/) ) {
        printf "%s", substr($0,1,RSTART-1) ENVIRON[substr($0,RSTART+1,RLENGTH-2)]
        $0 = substr($0,RSTART+RLENGTH)
    }
    print
}
' file

$ ./tst.sh
Running the build script...
Building finished at 04-14-2020
2005648:7445aa
On: MyLogin
current working directory: /home/MyLogin

, но если вы действительно хотите сделать несколько проходов, вызывая sed внутри оболочка l oop, тогда ${!variable} ваш друг, вот начало:

$ cat tst.sh
#!/bin/env bash

VAR1='2005648'
VAR2='7445aa'
SERVER_NAME='foo'

for var in VAR1 VAR2 SERVER_NAME; do
    echo "var, $var, ${!var}"
done

$ ./tst.sh
var, VAR1, 2005648
var, VAR2, 7445aa
var, SERVER_NAME, foo

.

$ VAR1='stuff'
$ var='VAR1'; echo 'foo {VAR1} bar' | sed "s/{$var}/${!var}/"
foo stuff bar

Скрипт awk устойчив, но YMMV использует sed в зависимости от содержимого переменных, например, произойдет сбой, если они содержат & или /, или \1, или .... ENVIRON [] имеет доступ только к переменным оболочки, установленным в командной строке awk или экспортированным, следовательно, экранирование в конец каждой строки, которая устанавливает переменную оболочки, так что она является частью командной строки awk.

1 голос
/ 14 апреля 2020

Вы можете попробовать это.

#!/usr/bin/env bash

echo "Running the build script..."
VAR1="2005648"
VAR2="7445aa"
SERVER_NAME=$(hostname)
TIMESTAMP=$(date +%m-%d-%Y)

sed "s|{TIMESTAMP}|$TIMESTAMP|;s|{VAR1}|$VAR1|;s|{VAR2}|$VAR2|;s|{SERVER_NAME}|$SERVER_NAME|;s|{PWD}|$PWD|" file.txt

Просто добавьте {} в переменные, например, {$TIMESTAMP} и т. Д., Если вам это действительно нужно.

Это должно работать, если нет это нечто большее, что не входит в вопрос выше.

...