달러가 작동하지 않는 Sed 쉘 스크립트 문자열

달러가 작동하지 않는 Sed 쉘 스크립트 문자열

sed로 대체될 두 개의 PHP 파일이 있습니다.

첫 번째는

$db['default'] = array(
    'dsn' => '',
    'hostname' => 'localhost',
    'username' => 'demo',
    'password' => 'demopass',
    'database' => 'dbname'
);

쉘 스크립트의 dbname을 동적 변수로 바꿔야 합니다. 이 스크립트를 사용하여 작업했습니다.

sed -i -e "/.*'database' =>*./ s/.*/'database' => '$1',/" /var/www/project/application/config/database.php

두 번째 파일은

$config['timezone'] = 'Asia/Jakarta';
$config['sess_cookie_name'] = 'sess_project';

"Asia/Jakarta"를 다른 동적 변수로 변경해야 하는데 시작 부분에 $ 기호가 있어서 작동하지 않습니다. 이게 내 코드야

sed -i -e "/.*$config['timezone'] = *./ s/.*/$config['timezone'] = '$2';/" /var/www/project/application/config/config.php

감사해요

답변1

이것은 실제로 처음에 보이는 것보다 더 흥미롭습니다.

적어도 GNU sed에서는 $패턴 끝에 나타날 때만 정규식 메타 문자로 간주되는 것처럼 보입니다. 예를 들어:

$ echo 'config$' | sed 's/config$/foobar$/'
config$

될 필요가

$ echo 'config$' | sed 's/config\$/foobar$/'
foobar$

$~에

$ echo '$config' | sed 's/$config/$foobar/'
$foobar

직장으로 탈출할 필요가 없습니다.하지만, 리터럴 작은따옴표를 포함할 수 있도록 sed 표현식 주위에 약한(큰) 따옴표를 사용하고 있으므로 이를 방지하려면 $in을 이스케이프해야 합니다.$config껍데기확장합니다(아마도 null 값으로). 셸이 확장을 수행하기 때문에 교체된 RHS에서도 이스케이프해야 합니다(정규식 메타 문자로 처리되지 않음).

반면에 [(즉 ,아니요큰따옴표는 쉘에 특별합니다)위치에 관계없이 정규식 메타 문자로 처리되므로 이스케이프해야 합니다. ](unescaped) 가 앞에 오지 않으면 이스케이프가 필요하지 않습니다 [.

마지막으로 확장에 $2슬래시(대체 Asia/Jakarta)가 포함될 수 있는 경우 해당 슬래시도 이스케이프 처리해야 합니다. 그렇지 않으면 sed 구분 기호를 다른 문자로 변경해야 합니다.

그래서 주어진

$ cat config.php
$config['timezone'] = 'Asia/Jakarta';
$config['sess_cookie_name'] = 'sess_project';

그리고

var='North America/Chicago'

그 다음에

$ sed -e "/.*\$config\['timezone'] = .*/ s/.*/\$config['timezone'] = '${var//\//\\\/}';/" config.php
$config['timezone'] = 'North America/Chicago';
$config['sess_cookie_name'] = 'sess_project';

*.(또한 가정된 유형을 로 수정하겠습니다 .*) 또는 더 간단하게

sed -e "/\$config\['timezone']/ s/=.*/= '${var//\//\\\/}';/" config.php

인용하다:

  1. sh 스크립트에서 sed를 사용할 때 어떤 문자를 이스케이프해야 합니까?
  2. sed 찾기 및 슬래시로 바꾸기

답변2

귀하의 sed는 지나치게 복잡한 것 같습니다. 나는 제안하고 싶습니다 (이 스크립트가 호출된다고 가정 t):

!/bin/bash
sed -i -e "s~\$config['timezone']\s*=\s*'.*';~\$config['timezone'] = '$1';~i" /var/www/project/application/config/config.php

다음과 같이 호출하세요 ./t 'Asia/Novokuznetsk'. 슬래시는 정규식 구분 기호로 인해 이스케이프되지 않습니다 ~. 를 제외하고 달러 기호는 이스케이프됩니다 $1.

답변3

repl_rhs=$(printf '%s\n' "$1" | sed -e 's:[\&/'\'']:\\&:g')
sed -e "
  /\(\$config[[]'timezone'] =\).*/s//\1 '$repl_rhs'/
" file.php
  • rhs 메타문자 + s/// 구분 기호 + PHP 작은따옴표 문자열을 이스케이프하세요.
  • 대체 문자열 $1에 개행 문자가 없습니다.

관련 정보