bash 쉘을 사용하여 검색 및 교체를 시도하고 있습니다. 다음과 같은 줄이 포함된 파일이 있습니다.
...
INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '฿');
...
각 행을 다음으로 변환하고 싶습니다.
currency = Currency.find_by_iso('THB') || Currency.new(:code => 'THB')
보시다시피 INSERT SQL 명령에서 두 번째 매개변수를 추출했습니다. 난 내가 할 수 있을 거라 생각했어
perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES ('(.*?)', '(.*?)', '(.*?)');/currency = Currency.find_by_iso(\$&) || Currency.new(:code => '\$&')/" currencies.rb
그러나 아무 일도 일어나지 않습니다. 즉, 교체된 출력이 라인을 변경하지 않고 그대로 둡니다. SQL 문에서 두 번째 값을 캡처하고 그 값에서 새 행을 만드는 방법은 무엇입니까?
답변1
교체된 출력은 라인을 변경하지 않고 그대로 둡니다.
이는 정규 표현식이 입력과 일치하지 않음을 나타냅니다. 따라서 한 걸음 물러서서 작동하는 최소 정규 표현식을 얻을 수 있는지 살펴보겠습니다.
perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES ('(.*?)', '(.*?)', '(.*?)');//" currencies.rb
> INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');
교체 부품을 제거하면 당연히 원래 구입한 부품과 차이가 없으며 입력과 일치하지 않습니다.
이제 정규식의 마지막 부분에는 ('(.*?)', '(.*?)', '(.*?)')
정규식에서 특별한 의미를 갖는 문자 할당이 포함되어 있으므로 이를 제거하고 작동하는지 살펴보겠습니다.
perl -w -pe "s/INSERT INTO currency (name, code, symbol) VALUES .*;//" currencies.rb
> INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');
여전히 일치하는 항목이 없습니다. 이제 유일한 특수 문자는 ()
이스케이프해야 할 문자뿐입니다.
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES .*;//" currencies.rb
>
예, 일치합니다. 입력이 일치하여 제거되었으므로 후행 비트를 다시 추가하고 이번에는 다른 ()
비트도 이스케이프 처리합니다.
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);//" currencies.rb
>
여전히 일치하므로 대체 항목을 다시 추가해 보겠습니다.
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$&) || Currency.new(:code => '\$&')/" currencies.rb
> currency = Currency.find_by_iso(INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');) || Currency.new(:code => 'INSERT INTO currency (name, code, symbol) VALUES ('Baht', 'THB', '?');')
흠, 잘못된 부분이 일치하는 것 같습니다. 이는 &가 원하는 개별 하위 그룹 이 아닌 전체 일치 표현식으로 대체되기 때문입니다 $1
.$2
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('(.*?)', '(.*?)', '(.*?)'\);/currency = Currency.find_by_iso(\$2) || Currency.new(:code => '\$2')/" currencies.rb
> currency = Currency.find_by_iso(THB) || Currency.new(:code => 'THB')
거의 거기에서 일부 인용문이 누락되었습니다. 다른 두 하위 그룹도 일치할 필요가 없으므로 제거하겠습니다.
perl -w -pe "s/INSERT INTO currency \(name, code, symbol\) VALUES \('.*?', '(.*?)', '.*?'\);/currency = Currency.find_by_iso('\$1') || Currency.new(:code => '\$1')/" currencies.rb
> currency = Currency.find_by_iso('THB') || Currency.new(:code => 'THB')
그게 바로 우리가 원했던 것입니다.
작동하지 않는 것처럼 보이는 복잡한 정규 표현식에 직면하면 일반적으로 언어 및 도구마다 다른 일부 특수 문자의 문제입니다. 때로는 이스케이프가 필요할 때도 있고 그렇지 않을 때도 있습니다. 정확히 원하는 부분이 아니더라도 입력의 일부와 일치하는 정규식을 얻을 때까지 먼저 더 간단한 대안을 사용하여 해당 문자를 제거하는 데 도움이 됩니다. 그런 다음 거기에서 조금씩 작업하십시오. 휴식을 취하거나 원하는 것을 얻습니다. 이 문제가 발생하는 경우 사용 중인 언어/도구에 대한 설명서를 읽어 실제로 원하는 구문이 무엇인지 알아내야 합니다.