정규식을 사용하여 파일에서 하나 또는 두 개의 서로 다른 패턴을 바꿉니다.

정규식을 사용하여 파일에서 하나 또는 두 개의 서로 다른 패턴을 바꿉니다.

input.txt파일에 다음과 같은 여러 문자열이 포함되어 있다고 가정합니다 .

[[foo>a|a]]
[[foo>b|b]]
[[foo>c|c]]

나는 다음으로 바꾸고 싶다:

:foo:`a`
:foo:`b`
:foo:`c`

나는 sed이 결과를 사용하거나 달성 할 수 있다고 생각합니다 rg(나는 그것을 사용한 적이 없습니다 awk).

하지만 파일에는 다음과 같은 다른 문자열도 포함되어 있습니다.

[[foo>a|d]]
[[foo>b|e]]
[[foo>c|f]]

나는 다음으로 바꾸고 싶다:

:foo:`d <a>`
:foo:`e <b> `
:foo:`f <c>`

두 가지 다른 모드를 동시에 처리하는 방법을 모르기 때문에 모든 시도가 실패했습니다.

후자의 결과(그리고 전자의 결과)를 얻을 수 있는 몇 가지 방법을 알고 있습니까?

답변1

표준 sed 구문을 사용하십시오.

sed '
  s/^\[\[\(.*\)>\(.*\)|\2\]\]$/:\1:`\2`/; t
  s/^\[\[\(.*\)>\(.*\)|\(.*\)\]\]$/:\1:`\3 <\2>`/'

답변2

주변을 살펴보면 주변 문자열이 |동일한지 확인할 수 있습니다. 예를 들어:

$ cat ip.txt 
[[foo>a|d]]
[[foo>b|e]]
[[foo>c|f]]

# same as: rg -NP '\[\[([^>]+)>([^|]+)\|(?!\2])([^|]+)]]' -r ':$1:`$3 <$2>`'
$ perl -pe 's/\[\[([^>]+)>([^|]+)\|(?!\2])([^|]+)]]/:$1:`$3 <$2>`/' ip.txt 
:foo:`d <a>`
:foo:`e <b>`
:foo:`f <c>`

(?!\2])|주변 문자열이 다른지 확인하기 위한 부정적인 예측 어설션입니다 .


두 가지를 모두 달성하려면 대체 섹션에서 플래그와 함께 Perl 코드를 사용할 수 있습니다 e.

$ cat ip.txt
[[foo>a|a]]
[[foo>b|b]]
[[foo>c|c]]

[[foo>a|d]]
[[foo>b|e]]
[[foo>c|f]]

$ perl -pe 's/\[\[([^>]+)>([^|]+)\|([^|]+)]]/":$1:`$3" . ($2 eq $3 ? "`" : " <$2>`")/e' ip.txt 
:foo:`a`
:foo:`b`
:foo:`c`

:foo:`d <a>`
:foo:`e <b>`
:foo:`f <c>`

여기서는 주변 문자열이 동일한지 여부에 따라 문자열이 선택됩니다 ($2 eq $3 ? "`" : " <$2>`").|

답변3

이 작업을 2~3개의 개별 부분으로 나눌 수 있을 것 같습니다. 먼저 squeeze( -s)하고 일부 문자를 로 대체하여 tr출력의 "개요"를 생성한 다음 a를 사용하여 sed두 개의 문자가 일치할 때 하나와 두 문자가 일치하지 않을 때로 두 개의 별도 대체를 만듭니다.

< file tr -s '[<>|]' ':::``' | sed -E 's/(.)`\1`/`\1`/; s/([^:])`(.)`/`\2 <\1>`/'

시험:

$ cat file
[[foo>a|a]]
[[foo>b|b]]
[[foo>c|c]]
[[foo>a|d]]
[[foo>b|e]]
[[foo>c|f]]

$ <file tr -s '[<>|]' ':::``' | sed -E 's/(.)`\1`/`\1`/;s/([^:])`(.)`/`\2 <\1>`/' 
:foo:`a`
:foo:`b`
:foo:`c`
:foo:`d <a>`
:foo:`e <b>`
:foo:`f <c>`

답변4

awk주어진 두 가지 형식의 처리를 관리하는 데 사용됩니다 .

awk -F'\\[\\[|\\]\\]|>|\\|' '{
    print $1, $2, "`" ($3==$4? $3 : $4" <"$3">") "`";
}' OFS=':' infile

테스트 입력:

[[foo>a|a]]
[[foo>bb|bb]]
[[foo>c|ccc]]
[[foo>aaaa|d]]
[[foo>b|ddd]]
[[foo>cccc|fff]]

산출:

:foo:`a`
:foo:`bb`
:foo:`ccc <c>`
:foo:`d <aaaa>`
:foo:`ddd <b>`
:foo:`fff <cccc>`

관련 정보