텍스트 파일을 구문 분석하면 숫자 앞과 뒤에 세미콜론이 추가됩니다. 숫자 앞/사이에 다른 모든 단어는 하이픈으로 표시됩니다.

텍스트 파일을 구문 분석하면 숫자 앞과 뒤에 세미콜론이 추가됩니다. 숫자 앞/사이에 다른 모든 단어는 하이픈으로 표시됩니다.

다음 계정이 포함된 텍스트 파일이 있습니다.

입력 샘플

Paid 100 15/02/2022 3000
recd 50 15/02/2022 nelur trip 3050
PAID 80 25/03/2022 Adjusted towards trip 3130
14 PAID 50  26/03/2022 Given to Nate Cash (padma ac) 3180

시작 부분의 숫자를 무시하거나 첫 번째 단어에 연결하고 싶습니다. 그런 다음 첫 번째 단어를 대시/하이픈으로 연결하고 날짜를 입력한 다음 단어를 입력합니다. 숫자를 추가하므로 새 줄을 제외하고 공백을 제거하십시오.

Linux 노트북에 쉽게 설치하고 실행할 수 있는 스크립트, perl/php, bash, awk, sed 등이 될 수도 있습니다.

출력 샘플

Paid;100;15/02/2022;3000
recd;50;15/02/2022;nelur-trip;3050
PAID;80;25/03/2022;Adjusted-towards-trip;3130
14-PAID;50;26/03/2022;Given-to-Nate-Cash-(padma-ac);3180

이것을 스프레드시트로 가져오고 싶으므로 다른 방법도 가능합니다. 약 300줄이 있습니다.

이전에 무엇을 시도했습니까? 스프레드시트를 사용하여 이미지 및 이미지-텍스트 변환기에서 얻은 데이터를 정리합니다.

또한 notepad++ 및 열 선택을 사용해 보았습니다. 나는 빨리 AWK를 배우려고 노력했다. 나는 Java를 알고 있지만 시간이 오래 걸립니다. 답변을 받은 후 몇 가지 사실을 배웠습니다.

  1. 줄 번호가 있는 경우 이를 유지하면 awk를 사용할 때 어떤 줄이 누락되었는지 파악하는 데 도움이 됩니다. AS는 건너뛴 줄에 대한 경고 없이 출력을 제공합니다. 어쩌면 그것을 우회하는 설정일 수도 있지만 확실하지 않습니다.
  2. csv, 스프레드시트 또는 PDF 형식의 계정은 항상 요청되며 이미지는 허용되지 않습니다!

우리 계정의 친구로부터 받은 이미지에 이미지를 텍스트로 실행하여 입력을 받습니다.

답변1

perl -pe 's/(?:^[0-9]+|[^0-9])\K (?=[^0-9])/-/g;
          s/ /;/g
' -- file
  • -p입력을 한 줄씩 읽고 처리 후 각 줄을 인쇄합니다.
  • 첫 번째 교체는 Lookaround 어설션을 사용합니다.문자열 시작 부분에 공백 앞에 숫자가 있거나, 숫자는 아니지만 뒤에 숫자가 없으면 공백을 대시로 바꿉니다.;
  • 두 번째 대체는 나머지 공백을 세미콜론으로 대체합니다.

마지막 줄 뒤의 두 공백이 오타가 아닌 경우 두 번째 교체를 변경하여 인접한 모든 공백을 단일 세미콜론으로 교체 50해야 합니다 .s/ +/;/g

답변2

이제 답을 얻었으니...

세 번째 인수로 GNU awk를 사용하십시오 match().

awk -v OFS=';' '
    match($0,/\S\s+([0-9]+)\s+(([0-9]{2}\/){2}[0-9]{4})(\s+(.*\S))? ([0-9]+)$/,a) {
        $0 = substr($0,1,RSTART) OFS a[1] OFS a[2] OFS a[5] OFS a[6]
        gsub(/\s+/,"-")
        print
    }
' file
Paid;100;15/02/2022;;3000
recd;50;15/02/2022;nelur-trip;3050
PAID;80;25/03/2022;Adjusted-towards-trip;3130
14-PAID;50;26/03/2022;Given-to-Nate-Cash-(padma-ac);3180

위의 내용은 입력 형식이 다음과 같다고 가정합니다.

<anything1> <integer1> <date>[ <anything2>] <integer2>
  (.*\S)     ([0-9]+)     ^    ( (.*\S))?    ([0-9]+)
                          |
              (([0-9]{2}\/){2}[0-9]{4})

필드 사이에 개행이 아닌 공백이 있을 수 있는 경우, anything내부 필드는 <...>항상 공백이 아닌 것으로 끝나지만 공백이나 다른 문자를 포함할 수 있고, 정수 앞에 오는 날짜 문자열은 포함될 수 없으며 anything1, [ <anything2>]선택 사항이며 원하는 경우 출력이 다음과 같다고 가정해 보겠습니다.

<anything1>;<integer1>;<date>;<anything2>;<integer2>

이는 Paid;100;15/02/2022;3000예상 출력에서 ​​실제로 Paid;100;15/02/2022;;3000다음과 같아야 함을 의미합니다. 각 출력 행에는 OP가 원한다고 말한 대로 스프레드시트를 가져오는 데 사용되는 필드 수가 동일해야 합니다.

\S정규식 시작 부분에 단일을 사용하고 원래 예상했던 대로 배열 요소를 채우는 대신 substr()헤더 문자열을 가져오는 데 사용하고 있으며 이것이 실패할 것이라는 것을 깨달았으므로 질문에 게시된 예제 입력을 사용하겠습니다. 주어진 입력, 예를 들어:anything(.*\S)

Paid 100 15/02/2022 foo 100 15/02/2022 3000

여기서 줄에 2개의 날짜가 있고 두 번째 날짜 주위의 문자열이 나머지 정규식과 일치합니다. 예를 들어 이 수정된 입력과 맨 아래에 있는 문제의 줄은 다음과 같습니다.

$ cat file
Paid 100 15/02/2022 3000
recd 50 15/02/2022 nelur trip 3050
PAID 80 25/03/2022 Adjusted towards trip 3130
14 PAID 50  26/03/2022 Given to Nate Cash (padma ac) 3180
Paid 100 15/02/2022 foo 100 15/02/2022 3000

(.*\S)정규식 시작 부분에 사용하는 경우 바람직하지 않은 마지막 출력 줄에 유의하세요.

$ awk -v OFS=';' '
    match($0,/(.*\S)\s+([0-9]+)\s+(([0-9]{2}\/){2}[0-9]{4})(\s+(.*\S))? ([0-9]+)$/,a) {
        $0 = a[1] OFS a[2] OFS a[3] OFS a[6] OFS a[7]
        gsub(/\s+/,"-")
        print
    }
' file
Paid;100;15/02/2022;;3000
recd;50;15/02/2022;nelur-trip;3050
PAID;80;25/03/2022;Adjusted-towards-trip;3130
14-PAID;50;26/03/2022;Given-to-Nate-Cash-(padma-ac);3180
Paid-100-15/02/2022-foo;100;15/02/2022;;3000

제안된 스크립트를 사용하여 출력을 수정합니다.

$ awk -v OFS=';' '
    match($0,/\S\s+([0-9]+)\s+(([0-9]{2}\/){2}[0-9]{4})(\s+(.*\S))? ([0-9]+)$/,a) {
        $0 = substr($0,1,RSTART) OFS a[1] OFS a[2] OFS a[5] OFS a[6]
        gsub(/\s+/,"-")
        print
    }
' file
Paid;100;15/02/2022;;3000
recd;50;15/02/2022;nelur-trip;3050
PAID;80;25/03/2022;Adjusted-towards-trip;3130
14-PAID;50;26/03/2022;Given-to-Nate-Cash-(padma-ac);3180
Paid;100;15/02/2022;foo-100-15/02/2022;3000

댓글의 피드백을 기반으로 편집하세요. 정규식과 일치하지 않는 줄을 기록하세요.

awk -v OFS=';' '
    match($0,/\S\s+([0-9]+)\s+(([0-9]{2}\/){2}[0-9]{4})(\s+(.*\S))? ([0-9]+)$/,a) {
        $0 = substr($0,1,RSTART) OFS a[1] OFS a[2] OFS a[5] OFS a[6]
        gsub(/\s+/,"-")
        print
        next
    }
    { print > "/dev/stderr" }
' file 2>unmatched.log

답변3

sed -E 's,([^0-9 ]) +([^0-9 ]),\1-\2,g
        s,^([0-9]+) +,\1-,g
        s, +,;,g
'

답변4

사용행복하다(이전 Perl_6)

먼저 구문 분석할 모든 행을 얻을 수 있는지 확인하십시오.

~$ raku -ne '.match(/ ^ \d* \s? <.alpha>+ \s \d+ \s [ \d**2 \/ \d**2 \/ \d**4 ] \s [[<.graph>+]+ % " " \s]? \d+ $ /).say;'  file

위의 내용은 Perl 프로그래밍 언어 제품군 중 유니코드를 지원하는 Raku의 한 가지 접근 방식입니다. 복잡한 정규식 문제로 시작하기 때문에 처음부터 끝까지 모든 줄이 올바르게 구문 분석되는 것을 보는 것이 가장 좋습니다 /^ … $/. ( raku -pe 's:g/\s+/ /;'먼저 공백 정규화와 같은 작업을 실행 해야 할 수도 있습니다 ). 위 코드는 NilOP의 결과인 올바르게 구문 분석되지 않은 행을 반환합니다.빈 정규화데이터:

입력 예:

Paid 100 15/02/2022 3000
recd 50 15/02/2022 nelur trip 3050
PAID 80 25/03/2022 Adjusted towards trip 3130
14 PAID 50 26/03/2022 Given to Nate Cash (padma ac) 3180

구문 분석 라인:

「Paid 100 15/02/2022 3000」
「recd 50 15/02/2022 nelur trip 3050」
「PAID 80 25/03/2022 Adjusted towards trip 3130」
「14 PAID 50 26/03/2022 Given to Nate Cash (padma ac) 3180」

이제 모든 행이 처음부터 끝까지 구문 분석되고 일치하는 요소를 캡처할 수 있음을 알 수 있습니다. 캡처를 나타내려면 괄호를 사용하십시오. Raku 캡처는 다음으로 시작됩니다 $0.

~$ raku -ne '.match(/ ^ (\d* \s? <.alpha>+) \s (\d+) \s ( \d**2 \/ \d**2 \/ \d**4 ) \s [(<.graph>+)+ % " " \s]? (\d+) $ /).say;'  file
「Paid 100 15/02/2022 3000」
 0 => 「Paid」
 1 => 「100」
 2 => 「15/02/2022」
 4 => 「3000」
「recd 50 15/02/2022 nelur trip 3050」
 0 => 「recd」
 1 => 「50」
 2 => 「15/02/2022」
 3 => 「nelur」
 3 => 「trip」
 4 => 「3050」
「PAID 80 25/03/2022 Adjusted towards trip 3130」
 0 => 「PAID」
 1 => 「80」
 2 => 「25/03/2022」
 3 => 「Adjusted」
 3 => 「towards」
 3 => 「trip」
 4 => 「3130」
「14 PAID 50 26/03/2022 Given to Nate Cash (padma ac) 3180」
 0 => 「14 PAID」
 1 => 「50」
 2 => 「26/03/2022」
 3 => 「Given」
 3 => 「to」
 3 => 「Nate」
 3 => 「Cash」
 3 => 「(padma」
 3 => 「ac)」
 4 => 「3180」

최종 답변 - Raku .subst( /…/, {…} )또는 Raku의 s///대체 명령/숙어를 사용하십시오. 참고: 두 대체 관용구 모두 대체 시 중괄호 안에 "호출 가능" 코드를 배치하여 각 명령의 기능을 크게 향상시킵니다. 따라서 .trans나머지 공백 문자를 -하이픈에 추가한 다음 join세미콜론 에 추가할 수 있습니다 ;.

~$ raku -ne '.subst(/ ^ (\d* \s? <.alpha>+) \s (\d+) \s ( \d**2 \/ \d**2 \/ \d**4 ) \s [(<.graph>+)+ % " " \s]? (\d+) $/,  \
             {join ";", $0.trans(" " => "-"), $1, $2, $3.trans(" " => "-") // "", $4}).put;'  file

#OR:

~$ raku -pe 's/ ^ (\d* \s? <.alpha>+) \s (\d+) \s ( \d**2 \/ \d**2 \/ \d**4 ) \s [(<.graph>+)+ % " " \s]? (\d+) $  \
              /{join ";", $0.trans(" " => "-"), $1, $2, $3.trans(" " => "-") // "", $4}/;'  file

출력 예(위 솔루션 중 하나):

Paid;100;15/02/2022;;3000
recd;50;15/02/2022;nelur-trip;3050
PAID;80;25/03/2022;Adjusted-towards-trip;3130
14-PAID;50;26/03/2022;Given-to-Nate-Cash-(padma-ac);3180

보너스 포인트: 예표준화{$0.uc}첫 번째 열을 모두 등으로 변환하는 것과 PAID같은 RECD것을 사용하는 경우

가정 단순화: 정규식을 단순화하여 \d숫자와 \D숫자가 아닌 항목을 처리할 수 있지만 영국 우편번호나 항공사 확인 코드(특히 열 4 중간)와 같이 숫자/숫자가 아닌 "단어"가 혼합된 행을 구문 분석하지 못할 수도 있습니다. ).

https://docs.raku.org/routine/subst#Callable
https://docs.raku.org/언어/regexes
https://raku.org

관련 정보