100개가 넘는 jinja 템플릿 파일이 있고 "value: ..." 문자열이 각 파일에 0-k번 나타납니다. 문제는 일부 파일이 다음을 사용하고 있다는 것입니다.
value: something
그 중 일부는 다음과 같습니다:
value: 'something'
그들 중 일부:
value: "some other thing"
큰따옴표를 사용하여 모두 동일하게 보이도록 해야 합니다. 나는 이 작업을 수행하기 위해 sed를 사용할 것이라고 생각합니다.
sed -i 's/value: ['"]?(.*)['"]?/value: "\1"/g' *.j2
하지만 보시다시피 저는 sed를 너무 싫어해서 지난 2시간 동안 종료되지 않은 "s" 명령 등과 같은 무의미한 오류 메시지로 키보드를 파괴하고 싶었습니다.
입력 예:
- param:
name: Command
type: String
value: '/bin/echo'
- param:
name: Args
type: String
value: Hello World
- param:
name: Something
type: EnvVar
value: "PATH"
이것으로부터 나는 다음을 얻어야 합니다:
- param:
name: Command
type: String
value: "/bin/echo"
- param:
name: Args
type: String
value: "Hello World"
- param:
name: Something
type: EnvVar
value: "PATH"
답변1
"'
표현식에 두 가지 형태의 따옴표()를 모두 사용해야 하면 상황이 까다로워집니다. 먼저, 초기 시도에서 쉘은 이를 's/value: ['
인용된 문자열로 식별합니다. 후자의 인용문은 보존되지 않습니다.
이러한 경우에는 걱정할 필요가 없습니다. Sed 명령을 파일에 넣으면 됩니다. 그 내용은 쉘 조작의 대상이 되지 않습니다.
quotes.sed
:
# (1) If line matches this regex (value: '),
# (2) substitute the first ' with " and
# (3) substitute the ' in the end-of-line with ".
/value: '/{
s/'/"/
s/'$/"/
}
# (4) If line matches this regex (value: [^"]),
# (5) substitute :<space> for :<space>" and
# (6) append a " in the end-of-line.
/value: [^"]/{
s/: /: "/
s/$/"/
}
$ sed -Ef quotes.sed file
- param:
name: Command
type: String
value: "/bin/echo"
- param:
name: Args
type: String
value: "Hello World"
- param:
name: Something
type: EnvVar
value: "PATH"
답변2
통화 sed
에 두 가지 문제가 있습니다.
- 작은따옴표로 묶인 프로그램에서는
['"]
정규식의 일부로 리터럴 작은따옴표를 포함합니다.sed
작은따옴표 안의 작은따옴표는 이스케이프할 수 없기 때문에 작동하지 않습니다. 그러나 로 표현할 수 있습니다\x27
. - 이
... (.*) ...
구문은 확장된 정규식 구문(
이며)
기본적으로 "그룹 캡처"를 의미합니다.-E
옵션을 사용sed
하거나 캡처 그룹을\(.*\)
사용 하여 정의해야 합니다.기본 정규식?
(그러나 비슷한 것으로 교체 해야 합니다\{0,1\}
.)
내 테스트에서는 다음이 작동합니다.
sed -E 's/value: [\x27"]?([^\x27"]*)[\x27"]?/value: "\1"/' input.j2
답변3
GNU awk를 사용하여 match() 및 gensub()에 세 번째 인수를 전달합니다.
$ awk 'match($0,/(\s*value:\s*)(.*)/,a){$0=a[1] "\"" gensub(/[\047"]/,"","g",a[2]) "\""} 1' file
- param:
name: Command
type: String
value: "/bin/echo"
- param:
name: Args
type: String
value: "Hello World"
- param:
name: Something
type: EnvVar
value: "PATH"
그렇지 않으면 awk를 사용하십시오.
$ awk '/value:/{hd=$0; sub(/:.*/,": ",hd); gsub(/[^:]*: *[\047"]?|[\047"]$/,""); $0=hd "\"" $0 "\""} 1' file
- param:
name: Command
type: String
value: "/bin/echo"
- param:
name: Args
type: String
value: "Hello World"
- param:
name: Something
type: EnvVar
value: "PATH"
답변4
Raku(이전 Perl6) 사용
Larry Wall이라는 신사가 "perl6-users" 메일링 리스트에 이 깔끔한 인용 팁을 올렸습니다.[이메일 보호됨]). 아래 NNTP 링크의 팁 #8을 참조하세요.
~$ env re="\'" raku -ne 'say $0 if m/ <?after value\:\s > \"? <{ %*ENV<re> }>? (.+?) \"? <{ %*ENV<re> }>? $$ /;' jinja.txt
「/bin/echo」
「Hello World」
「PATH」
위의 코드는 올바른 일치를 보여줍니다. 따라서 필요한 것은 다음 코드를 실행하는 것뿐입니다.
~$ env re="\'" raku -pe 's/ <?after value\:\s > \"? <{ %*ENV<re> }>? (.+?) \"? <{ %*ENV<re> }>? $$ /"{$0}"/;' jinja.txt
- param:
name: Command
type: String
value: "/bin/echo"
- param:
name: Args
type: String
value: "Hello World"
- param:
name: Something
type: EnvVar
value: "PATH"
탈출을 더 읽기 쉽게 만들고 싶습니까? 위와 같은 ENV 변수를 사용하고 싶지 않으신가요? 그런 다음 인용 문자의 철자를 입력하세요(아래 NNTP 링크의 Larry Wall의 팁 #8에서도 참조).
~$ raku -ne 'say $0 if m/ <?after value\:\s > \c[QUOTATION MARK]? \c[APOSTROPHE]? (.+?) \c[APOSTROPHE]? \c[QUOTATION MARK]? $$ /;' jinja.txt
「/bin/echo」
「Hello World」
「PATH」
~$ raku -pe 's/ <?after value\:\s > \c[QUOTATION MARK]? \c[APOSTROPHE]? (.+?) \c[APOSTROPHE]? \c[QUOTATION MARK]? $$ /"{$0}"/;' jinja.txt
- param:
name: Command
type: String
value: "/bin/echo"
- param:
name: Args
type: String
value: "Hello World"
- param:
name: Something
type: EnvVar
value: "PATH"
HTH.
https://raku.org/
https://www.nntp.perl.org/group/perl.perl6.users/2020/07/msg9004.html