단일 문자 인스턴스와 일치하는 정규식

단일 문자 인스턴스와 일치하는 정규식

나는 직장에서 이것을 유지 관리하고 있으며 다소 난해한 DSL을 사용합니다. 그리고 그 도구는 그다지 좋지 않습니다. 잘못된 툴링 문제를 해결하기 위해 코드를 프로덕션으로 보내기 전에 코드의 몇 가지 문제를 찾는 스크립트를 작성했습니다.

제가 현재 해결하려는 문제는 변수 이름과 관련이 있습니다. 변수 이름은 과 같이 지정됩니다 @@Variable@@. 1초만 있거나 @2초 이상 이면 @치명적인 오류입니다.

이제 문제의 파일을 반복하면서 @@@연속해서 3개 이상을 발견하면 오류가 발생합니다 @. 그래서 그 부분이 멋있어요.

하지만 나는 독신 생활에 좀 갇혀 있습니다 @. 한 줄에 여러 변수가 있을 수 있습니다.

@@Var1@@ words words words @@Var2@@  #This works
@Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
@@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.

위의 순열은 다양하며 한 줄의 변수 수에는 제한이 없습니다.

이 awk 스크립트는 특정 줄에 변수가 하나만 있는 경우 작동하지만 한 줄에 변수가 여러 개 있는 경우에는 작동하지 않습니다.

awk '/@/ && ! /@@.*@@/' test.txt

실제로 해야 할 일은 하나만 일치시키는 것입니다 @. 위의 예제 코드에서는 행 1을 제외한 모든 행과 일치합니다.

답변1

$ sed 'h;s/@@[^@ ]*@@//g;/@/!d;g' file
@Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
@@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.

sed명령은 유효한 변수 자리 표시자를 제거하고 여전히 문자가 포함된 행을 보고합니다 @. 또한 @양쪽에 두 개 이상의 자리 표시자가 포함된 줄을 찾습니다 .

각 행을 예약된 공간에 저장하여 원래 실패한 행을 보고할 수 있습니다 h. 그런 다음 잠재적으로 유효한 자리 표시자를 제거하는 바꾸기를 실행하고 그 뒤에 문자가 포함되어 있지 않으면 @줄을 삭제합니다. 예약된 공간에서 원래 줄을 가져와서 g존재하는 경우 인쇄합니다.

변수가 대부분의 프로그래밍 언어와 동일한 명명 규칙을 따르는 경우 @@[^@ ]*@@유효한 자리 표시자의 패턴을 로 변경할 수 있습니다.@@[[:alpha:]_][[:alnum:]_]*@@

@텍스트 자체에 문자를 포함 할 수 있어야 한다고 가정해 보겠습니다 . 이 경우 @위 명령에서 대체하기 전에 변수 자리 표시자가 아닌 유효한 별자리의 가능한 모든 항목을 제거 해야 합니다 .


@보다 체계적인 접근 방식은 한쪽 또는 다른쪽에 너무 많은 문자가 포함된 자리 표시자를 포함하는 줄을 추출하고 올바른 자리 표시자를 제거한 다음 @변수 이름 OK의 양쪽에 하나의 문자만 포함하도록 자리 표시자를 가져오는 것입니다.

sed -e '/@\{3,\}[^@ ]*@\{1,\}/b' \
    -e '/@\{1,\}[^@ ]*@\{3,\}/b' \
    -e h \
    -e 's/@@[^@ ]*@@//g' \
    -e '/@[^@ ]*@/!d' \
    -e g file

@위의 방법을 사용하면 문자가 자리 표시자처럼 보이는 패턴으로 표시되지 않는 한 텍스트에 다른 문자를 포함할 수 있습니다 .

답변2

$ grep -E '(^|[^@])@([^@]|$)|@@@' file
@Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
@@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.

또는:

$ awk '/(^|[^@])@([^@]|$)|@@@/' file
@Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
@@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.

또는 한 번에 하나의 필드를 분석합니다.

$ cat tst.awk
{
    for (i=1; i<=NF; i++) {
        if ( $i ~ /^@[^@]|[^@]@$|@@@/ ) {
            print "Failed line:", NR, $0
            print "\tbecause of field", i, $i
        }
    }
}

$ awk -f tst.awk file
Failed line: 2 @Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
        because of field 1 @Var1@@
Failed line: 3 @@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
        because of field 1 @@Var1@
Failed line: 4 @@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
        because of field 5 @Var2@@
Failed line: 5 @@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.
        because of field 5 @@Var2@

사건을 찾기 위해 추가로 필요한 것은 없으며 @@@, 위의 내용에는 사건 찾기도 포함됩니다.

답변3

또 다른 해결책은 grep -E정규 표현식이 awk에서도 작동하는 것입니다.

grep -E '[^@]@[^@]|^@[^@]|@[^@]$' tmpfile
@Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
@@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.

awk '/[^@]@[^@]|^@[^@]|@[^@]$/' tmpfile
@Var1@@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@ words words words @@Var2@@   #This will fail because Var1 is wrong.
@@Var1@@ words words words @Var2@@   #This will fail because Var2 is wrong.
@@Var1@@ words words words @@Var2@   #This will fail because Var2 is wrong.

답변4

지원되는 경우 음수 탐색 연산자를 사용하여 단일 s 또는 grep -Ps로 묶이지 않은 @3개 이상의 시퀀스를 일치시킬 수 있습니다.@@

<test.txt grep --color -P '(?<!@)(@|@{3,})(?!@)'

그러나 이는 여전히 표시되며 @@@@in 또는 와 같이 @@var1@@@@var2@@일치하지 않는 s를 표시할 수 없습니다 .@@@@var1@@var1@@var2@@

또 다른 방법은 다음과 같습니다.

<test.txt grep --color -P '@@\w+@@(*SKIP)(*FAIL)|@+'

이는 시퀀스의 @일부가 아닌 부분을 표시합니다 .@@word@@

$ <test.txt grep --color -P '@@\w+@@(*SKIP)(*FAIL)|@+' @Var1@@ 단어 단어 @@Var2@@ #Var1이 오류이므로 실패합니다. 의. @@Var1@wordswords@@Var2@@ #Var1이 잘못되었기 때문에 실패합니다. @@Var1@@wordswords@Var2@@#Var2가 잘못되었기 때문에 실패합니다. @@Var1@@wordswords@@Var2@#Var2가 잘못되었기 때문에 실패합니다.

관련 정보