(BASIC) 파일에서 문자열 추출

(BASIC) 파일에서 문자열 추출

문자열에서 모든 문자열을 추출하려고 합니다(나타나는 순서대로).타이판 BASIC 출시. "그러나 일부 문자열의 끝에 공백이 있고 이를 "보고" 계산할 수 있어야 하기 때문에 출력에도 구분 기호(문자열의 시작과 끝)가 표시되기를 원합니다 . 마지막은 "이 시점에서 완화될 것입니다).

설상가상으로 저는 macOS에서 실행 중이므로 일부 grep 매개변수가 GNUgrep과 다를 것입니다.

두 개의 문자열을 포함하는 예제 줄은 다음과 같습니다.

1270 VTAB 19:PRINT " WE'VE CAPTURED A BIGGER SHIP!" : GOSUB 760:VTAB 19:PRINT " WE'RE TRANSFERRING TO IT NOW.": GOSUB 780:G = G + INT ( RND (1) * (G + 1)) + 1:E = SH + INT ( RND (1) * (SH + 150)) + 1: SH = SH + E:MW = MW + E:P=0

내가 필요한 출력은

...
" WE'VE CAPTURED A BIGGER SHIP!"
" WE'RE TRANSFERRING TO IT NOW."
...

"나는 using 1을 포함하는 줄만 얻었습니다.

grep -o '".*"'

그러나 이것은 탐욕스러운 grep이며 한 줄에 두 개 이상의 문자열을 얻고 다중 문 줄의 개별 문자열을 다른 줄에 출력하는 대신 문자열 사이에 문자열이 아닌 명령도 캡처합니다.

" WE'VE CAPTURED A BIGGER SHIP!" : GOSUB 760:PRINT TAB(0,18) " WE'RE TRANSFERRING TO IT NOW."

이것은 분명히 내가 원하는 것이 아닙니다.

다음 non-greedy는 grep제대로 작동하지 않는 것 같고 (어떤 이유로든) 출력에 더 적은 줄을 제공합니다. 아마도 해당 grep옵션을 macOS에서 사용할 수 없기 때문일 것입니다 -P.

grep -oP '".*?"'

어쨌든 출력을 계속해서 grep -o '".*"'입력 awk하고 찾으면심지어필드 3

grep -o '".*"' TAIPAN_BAS.txt | awk -F\" '{print $2}'
grep -o '".*"' TAIPAN_BAS.txt | awk -F\" '{print $4}'
grep -o '".*"' TAIPAN_BAS.txt | awk -F\" '{print $6}'

다중 명령문 라인의 두 번째(또는 세 번째 또는 후속) 문자열이 출력된다는 점을 제외하면 다소 결과가 나올 것입니다.그 후에야문자열의 첫 번째 항목이 모두 나열됩니다.

예를 들어 이것을 입력으로 사용하십시오.

1270 VTAB 19:PRINT " WE'VE CAPTURED A BIGGER SHIP!" : GOSUB 760:VTAB 19:PRINT " WE'RE TRANSFERRING TO IT NOW.": GOSUB 780:G = G + INT ( RND (1) * (G + 1)) + 1:E = SH + INT ( RND (1) * (SH + 150)) + 1: SH = SH + E:MW = MW + E:P=0
1280 IF SR < .1 THEN 1300 
1281 IF P > 0 THEN 1050 
1285 REM ARRIVAL (1290)
1290 CR = 0: SR = 1:L=PO:V(L) = V(L) + 1: B=0:K=0:GOSUB 160:HOME:PRINT:INVERSE:PRINT A$;: NORMAL: PRINT " ARRIVING "; L$(L);" AFTER": PRINT " A VOYAGE OF ";ET;" DAYS.": INVERSE:PRINT A$:NORMAL: GOSUB 780: HOME:GOTO 120

출력됩니다n번째"일괄"의 문자열:

<first command output>
 WE'VE CAPTURED A BIGGER SHIP!
 ARRIVING 
<second command output>
 WE'RE TRANSFERRING TO IT NOW.
 AFTER
<third command output>
 A VOYAGE OF 

이렇게 정렬하면 출력이 더 좋아질 것입니다.

 WE'VE CAPTURED A BIGGER SHIP!
 WE'RE TRANSFERRING TO IT NOW.
 ARRIVING 
 AFTER
 A VOYAGE OF 

그러나 이러한 "더 이상적인" 출력에도 여전히 두 가지 문제가 있습니다.

  • 마지막 문자열( " DAYS.")이 누락되었습니다. 하나 필요합니다.추가의여덟 번째 필드를 가져오는 명령은 다음과 같습니다.

    grep -o '".*"' TAIPAN_BAS.txt | awk -F\" '{print $8}'
    
  • 큰따옴표도 누락되었습니다.

이것이 내가 보고 싶은 것입니다(사용: 큰따옴표;모두문자열 길이 및 표시 순서):

" WE'VE CAPTURED A BIGGER SHIP!"
" WE'RE TRANSFERRING TO IT NOW."
" ARRIVING "
" AFTER"
" A VOYAGE OF "
" DAYS."

노트: 아포스트로피를 제외하고 문자열에는 따옴표(작은따옴표 또는 큰따옴표)가 포함되지 않습니다.

내 질문은 다음과 같습니다

  • 어떻게 찾을 수 있어?모두발행할 필요 없이 다중 명령문 라인의 필드까지분리명령은{print $2 $4 $6 ...}필드 - 프로그래밍 방식으로 표현하는 방법 이 없나요 awk?
  • 배치(첫 번째 문자열의 모든 항목, 두 번째 문자열의 모든 항목, 세 번째 문자열의 모든 항목 등)가 아닌 순서대로 표시되도록 두 번째 및 세 번째 문자열을 파일에 연결하려면 어떻게 해야 합니까?
    • 나는 이것을 시도했다

      grep -o '".*"' TAIPAN_BAS.txt | awk -F\" '{printf $2,"\\n"$4"\\n"$6}'
      

      그러나 모든 것이 한 줄에 출력되고 첫 번째 문자열 인스턴스만 출력되며 줄 바꿈( \\n)은 무시되는 것처럼 보입니다.

  • awk필드 구분 기호(예: ) 제거를 중지하려면 어떻게 해야 합니까 "?

이번에도 저는 macOS를 사용하고 있으므로 GNU 솔루션이 도움이 되지 않을 수 있습니다. 또한, 나는 그런 것을 기꺼이 사용할 것입니다 sed(나는 그것을 시도했지만 cut그들은 tr그것을 제거 "하고 많은 코드를 남겼습니다).


1 에서이 답변도착하다명령 출력에서 ​​따옴표 붙은 문자열의 내용을 추출하는 방법은 무엇입니까?

2번 다시 확인하면 "사용됨" 메시지만 표시됩니다.

3 에서이 답변도착하다큰따옴표 사이의 문자열 추출.

답변1

사용행복하다(이전 Perl_6)

~$ raku -ne '.put for .comb( / \" <-["]>+? \" /);'  file

또는:

~$ raku -ne '.put for .comb( / \" ~ \" <-["]>+?  /);'  file

다음은 Perl 계열의 프로그래밍 언어인 Raku로 작성한 답변입니다. Raku에는 코드 구문 분석을 위한 강력한 정규식/구문 엔진이 있습니다(참조:"Raku 문법의 간단한 파서").

위의 코드로 comb원하는 패턴을 검색 하실 수 있습니다. 사용자 정의 문자 클래스를 생성하려면 <+["]>긍정 및 <-["]>부정 선택 에 대한 따옴표를 찾으십시오 . 두 번째 답변은 Raku의 ~물결표 표기법을 사용합니다. 이는 중첩된 텍스트 요소 및/또는 주변 요소를 추출하는 데 유용합니다.

입력 예:

1270 VTAB 19:PRINT " WE'VE CAPTURED A BIGGER SHIP!" : GOSUB 760:VTAB 19:PRINT " WE'RE TRANSFERRING TO IT NOW.": GOSUB 780:G = G + INT ( RND (1) * (G + 1)) + 1:E = SH + INT ( RND (1) * (SH + 150)) + 1: SH = SH + E:MW = MW + E:P=0
1280 IF SR < .1 THEN 1300 
1281 IF P > 0 THEN 1050 
1285 REM ARRIVAL (1290)
1290 CR = 0: SR = 1:L=PO:V(L) = V(L) + 1: B=0:K=0:GOSUB 160:HOME:PRINT:INVERSE:PRINT A$;: NORMAL: PRINT " ARRIVING "; L$(L);" AFTER": PRINT " A VOYAGE OF ";ET;" DAYS.": INVERSE:PRINT A$:NORMAL: GOSUB 780: HOME:GOTO 120

1295 REM THAT'S ALL FOLKS (1300-1321)
1300 HOME:NW = C - D:Q = NW / GT: VTAB 4: INVERSE: PRINT A$;: NORMAL: PRINT:PRINT "YOUR SCORE, BASED UPON TIME AND YOUR": PRINT "NET WORTH (EXCLUDING STOCK) IS ";: GOSUB 1330:INVERSE: PRINT A$: NORMAL
1310 IF X$ = "R" THEN PRINT "WOULD YOU LIKE TO PICK UP THIS":PRINT"GAME WHERE YOU LEFT OFF (Y/N)?": GOSUB 60:IF X$ = "Y" THEN HOME:GOTO 120
1320 GOSUB 1340: VTAB 10:PRINT A$;: PRINT "DO YOU WISH TO START OVER (Y/N)?": GOSUB 60:IF X$ = "Y" THEN RUN
1321 END

예제 출력:

" WE'VE CAPTURED A BIGGER SHIP!"
" WE'RE TRANSFERRING TO IT NOW."
" ARRIVING "
" AFTER"
" A VOYAGE OF "
" DAYS."
"YOUR SCORE, BASED UPON TIME AND YOUR"
"NET WORTH (EXCLUDING STOCK) IS "
"R"
"WOULD YOU LIKE TO PICK UP THIS"
"GAME WHERE YOU LEFT OFF (Y/N)?"
"Y"
"DO YOU WISH TO START OVER (Y/N)?"
"Y"

위의 예제 출력은 시작을 위한 것입니다. 인용된 문자열이 발견된 줄 번호를 기록할 수도 있습니다.

~$ raku -e ' for lines.kv -> $k,$v { put "$k\t$_" for $v.comb( / \" <-["]>+? \" /)};' file
0   " WE'VE CAPTURED A BIGGER SHIP!"
0   " WE'RE TRANSFERRING TO IT NOW."
4   " ARRIVING "
4   " AFTER"
4   " A VOYAGE OF "
4   " DAYS."
7   "YOUR SCORE, BASED UPON TIME AND YOUR"
7   "NET WORTH (EXCLUDING STOCK) IS "
8   "R"
8   "WOULD YOU LIKE TO PICK UP THIS"
8   "GAME WHERE YOU LEFT OFF (Y/N)?"
8   "Y"
9   "DO YOU WISH TO START OVER (Y/N)?"
9   "Y"

grep마지막으로 "프로그램 줄 번호"를 반환하려는 경우 Raku가 오류를 일으키는 빈 줄을 필터링하므로 큰 도움이 될 수 있습니다.

~$ raku -e 'for lines.grep(*.chars).map( *.split(" ", 2)) { my $k = .[0];  my $v = .[1];  put "$k\t$_" for $v.comb( / \" <-["]>+? \" /) };'  file
1270    " WE'VE CAPTURED A BIGGER SHIP!"
1270    " WE'RE TRANSFERRING TO IT NOW."
1290    " ARRIVING "
1290    " AFTER"
1290    " A VOYAGE OF "
1290    " DAYS."
1300    "YOUR SCORE, BASED UPON TIME AND YOUR"
1300    "NET WORTH (EXCLUDING STOCK) IS "
1310    "R"
1310    "WOULD YOU LIKE TO PICK UP THIS"
1310    "GAME WHERE YOU LEFT OFF (Y/N)?"
1310    "Y"
1320    "DO YOU WISH TO START OVER (Y/N)?"
1320    "Y"

https://docs.raku.org/언어/regexes#Tilde_for_nesting_structs
https://docs.raku.org/언어/regexes
https://docs.raku.org
https://raku.org

답변2

-P옵션은 Perl을 나타내며 Perl 정규 표현식을 사용하므로 이를 사용할 수 없는 경우 Perl을 직접 사용할 수 있습니다...

% perl -lne 'print $& while /".*?"/g' file2.txt
" WE'VE CAPTURED A BIGGER SHIP!"
" WE'RE TRANSFERRING TO IT NOW."
" ARRIVING "
" AFTER"
" A VOYAGE OF "
" DAYS."

( $&완전한 일치 문자열이므로 이미 ".*?"그것이 무엇인지 알고 있습니다.)

그러나 물론 닫는 태그는 단 한 문자이므로 일반 경우에도 필수 두 개의 큰따옴표 사이에서 큰따옴표가 아닌 모든 항목을 일치시킬 수 있습니다 grep.

% grep -oe  '"[^"]*"' file2.txt

답변3

모든 Unix 시스템의 모든 쉘에서 awk를 사용하십시오.

$ awk -F'"' '{for (i=2; i<NF; i+=2) print FS $i FS}' file
" WE'VE CAPTURED A BIGGER SHIP!"
" WE'RE TRANSFERRING TO IT NOW."
" ARRIVING "
" AFTER"
" A VOYAGE OF "
" DAYS."

"위의 내용은 인용한 문자열에 s 또는 개행 문자가 없다고 가정합니다.

가능하다면 올바른 해결책은 "내부적으로 구분된 문자열이 표현되는 방식( 백슬래시 또는 기타 방법 "으로 두 배로 늘리거나 이스케이프하여 허용되지 않거나 이스케이프 되지 않음 )과 개행 문자를 처리하는 방법(있는 그대로 인쇄, 공백으로 변환 또는 기타 다른 방법)에 따라 달라집니다. ).""\"

관련 정보