GAWK는 FS에 대괄호를 사용합니다.

GAWK는 FS에 대괄호를 사용합니다.

FS에 대한 정규식이 space-open_parenthersis 또는 opening_parenesis-coma-space로 설정되어 있을 때 gawk 작업에 어려움을 겪고 있습니다. 여러 가지 접근 방식을 시도했지만 그 중 어느 것도 예상된 동작으로 이어지지 않았습니다. FS="( ()|(), )" 두번째. FS="[( ()(), )]"숫자 3(ASCII OCT 코드 사용) FS="[(\040\050)(\051\054\040)]"숫자 4FS="((\040\050)|(\051\054\040))"

내 입력 파일은 다음과 같습니다https://phpaste.sourceforge.io/demo/paste.php?id=144이것은 데비안의 apt-get 로그 중 단 하나의 레코드(라인)만 포함하고 일부 패키지를 나열하는 파일입니다.

내 gawk 프로그램은 다음과 같습니다

#! /usr/bin/gawk -f
BEGIN {FS = "[(\040\050)(\051\054\040]"}
{
for(i=1;i<=NF;i=i+2) #I increased i by 2 because i want to print the odd numbered fields(only the names of the packages:architecture)  
    print $i
}`

bash에서 실행하겠습니다.myawk.awk input.txt > output.txt


여기에 FXXX라는 큰 단어를 추가하고 싶습니다! ! ! ! 방금 해결했거든요. 계속해서 노력한 것에 대한 보상이라고 생각합니다. 나는 이 방법을 사용했지만 왜 ASCII 8진수 코드 앞에 백슬래시가 3개 있는지 FS = "(\\s\\\050)|(\\\051,\\s)"잘 이해하지 못했습니다 .\\\

누구든지 이것에 대해 설명을 제공할 수 있습니까? 왜요? ? 나는 AWK가 정규식을 두 번 읽는다는 것을 읽었는데, 이는 필수이지만 \\나는 그것이 필요합니다 \\\(세 번!!!).

대안이나 다른 접근 방식도 크게 감사하겠습니다!

미리 감사드립니다!

이것이 내가 원했던 결과이고 고맙게도 지난번 실행에서 얻었습니다.https://phpaste.sourceforge.io/demo/paste.php?id=145(아키텍처를 포함하는 패키지 목록)

답변1

당신은 이것을 지나치게 생각하고 있을 수도 있습니다. 조금. 나는 그것을 작동시키고 FS=" \\(|\\), "심지어 그것을 FS=" \\(|), ".

  • 당신은 그것을 해야 한다고 믿는 것처럼 보이지만 사실 당신이 해야 할 일은 그것뿐입니다."(regex1)|(regex2)""regex1|regex2"
  • 괄호를 그룹화 괄호 안에 넣으면 내부 괄호가 문자 그대로의 텍스트 괄호가 된다고 생각하는 것 같습니다. 그러나 실제로는 그렇지 않습니다. 정규식 그룹화는 중첩될 수 있습니다. 대괄호를 리터럴 텍스트 대괄호로 처리하려면 이를 이스케이프해야 합니다.
  • )그룹 내 정규식 내에서만 특별합니다. (이스케이프된 경우에는 )이스케이프가 필요하지 않습니다.

이것이 까다로워지는 곳입니다. 순진하게 말하면 위에서 보면 FS=" \(|), "충분할 것입니다. 그러나 GAWK에는 문자열 상수의 정규식에 문제가 있습니다.GNU Awk 사용자 가이드, 섹션 9.1.3.1. &, 또는 에 의해 호출되는 대체 텍스트에서 텍스트를 가져오는 데 중점을 두고 있지만 다음에서도 작동하는 것으로 보입니다.sub()gsub()gensub()FS

...여러 레벨이 있습니다이스케이프 처리진행 중입니다.

우선 다음과 같은 것들이 있습니다.어휘 수준, awk프로그램을 읽고 실행을 위해 내부 복사본을 만드는 데 걸리는 시간입니다. 그리고 awk[프로그램이 실제로 스캔되고 실행 방법을 결정]하는 런타임 수준이 있습니다 .

두 수준 모두에서 awk백슬래시 뒤에 나타날 수 있는 정의된 문자 집합을 찾습니다. 어휘 수준에서 나열된 이스케이프 시퀀스를 찾습니다.이스케이프 시퀀스따라서 awk런타임 수준에서 처리되는 모든 "\"에 대해 어휘 수준에서 두 개의 백슬래시를 입력해야 합니다.  …

강조가 추가되었습니다(마지막 문장). 이는 FS( " \(|), " 왼쪽 대괄호를 탈출하고 대괄호를 리터럴, 리터럴 대괄호로 처리)로 설정하려면 다음이 필요하다는 뜻인 것 같습니다.분배하다 FS=" \\(|), "또는 지정됨 -F' \\(|), ' (이스케이프된 백슬래시) 간단한 테스트를 통해 이를 확인할 수 있습니다. 실행한 awk -F' \\(|), '다음 FS프로그램에서 인쇄하세요. 로 표시됩니다 ⁠ \(|), ⁠.


일반적으로 특수 문자를 특수 문자가 아닌 문자로 변환하려는 경우(또는 그 반대로 변환하려는 경우) 일반적인 레거시 접근 방식은 \(백슬래시)를 사용하여 이스케이프하는 것입니다. 그러나 정규 표현식과 관련된 또 다른 메커니즘이 있습니다. 바로 표현식 사용입니다 […]. […]표현식의 유일한 특수 문자는 ^,-그리고 ](위치에 따라).

  • [pq]p하나 또는 하나를 의미q
  • [()](하나 또는 하나를 의미)
  • [(p](하나 또는 하나를 의미p
  • [(]  a (또는... 음, 다른 문자가 없으므로 텍스트만 의미합니다 (.

따라서 백슬래시에 알레르기가 있는 경우 설정할 수 있습니다 FS=" [(]|), ".

답변2

제가 생각해낸 또 다른 방법이 있습니다. 출력과 정확히 일치합니다. split()각 항목에 대한 추가 작업 으로 인해 효율성이 떨어질 수 있지만 읽고 이해하기는 더 쉽습니다.

#!/usr/bin/awk -f

BEGIN { 
    FS="), "
}
{
    sub(/^Install:/, "") 
    for (i=1; i<=NF; i++) { 
        split($i, a, " ")
        print a[1]
    }
}

답변3

awk를 사용하지 않고 동일한 작업을 수행하는 더 쉬운 방법이 있습니다. 주요 Linux 배포판에서 사용할 수 있는 다양한 버전의 grep과 함께 Perl 정규식을 사용할 수 있습니다. 내 grep 버전(GNU grep 버전 2.27)을 사용하면 다음은 awk 솔루션과 동일한 출력을 제공합니다.

grep -oP '(?<=\),).*?(?=\()' input.txt > output.txt

관련 정보