일부 패턴을 추출하기 위해 여러 텍스트 파일을 읽었습니다. 줄 번호도 필요하지만 최종 grep 전에 제거해야 합니다(그러나 추가 처리를 위해 변수를 사용하여 저장할 수 있습니다).
더 나은 이해를 위해 (긴 한 줄) 명령을 분할하는 과정을 설명하겠습니다.
파일 읽기고양이, 정리를 수행하십시오(다음을 사용하여 이상한 문자와 개행 문자를 제거하십시오).sed그리고티)등. 다음은 다양한 덕트 청소 작업의 예입니다.
cat file | sed 's/,/ /g' | sed '/^$/d'
줄 번호 및 탭 추가NL명령 및 추가 처리 및 정리
nl -nrz -w4 -s$'\t' | tr '\n\r' ' '
원하는 최종 스키마를 CSV 파일로 추출
grep -Eio '.{0,0}account number.{0,15}' >> account_list.csv
문제는 동일한 줄 명령(while 또는 루프는 허용되지 않음)을 사용하여 2단계의 행 번호를 정확히 동일한 CSV(순서에 관계없이 다른 열)로 보내야 하지만 지금까지는 성공하지 못했다는 것입니다.
[이해를 돕기 위해 수정했습니다] 필요한 줄 번호는 정리 전 파일의 원래 줄 번호라는 점을 고려하면. 이 청소 과정에서 때때로 구절이 삭제됩니다. 천 줄이 있는 파일을 상상해 보세요. 처리 후에 백 줄이 표시됩니다. 새 줄 번호가 잘못되었습니다. [편집 끝]
일부 처리 후 샘플 입력:
0123 the first account number 2345356432 must be used
0345 take it just for billing purposes, not any other.
0657 Meanwhile the second account number 8623525534
0987 user is blocked until the issue is solved with
원하는 출력은 다음과 같습니다.
2345356432; 0123
8623525534; 0657
또는
0123; 2345356432
0657; 8623525534
어떤 조언이라도 대단히 감사하겠습니다.
답변1
awk
정리하기 전에 원래 입력 파일에서 다음을 사용하십시오.
awk '/account number [[:digit:]]+/ { match($0, "account number ([[:digit:]]+)", a); print NR ";" substr($0, a[1, "start"], a[1, "length"]); }' input
그러면 계좌 번호가 추출되고 줄 시작 부분에 줄 번호가 인쇄됩니다.
1;2345356432
3;8623525534
정리된 파일에서 전처리된 숫자를 추출하려면 다음을 수행하십시오.
awk '/account number [[:digit:]]+/ { match($0, "account number ([[:digit:]]+)", a); print $1 ";" substr($0, a[1, "start"], a[1, "length"]); }' input
조금 분석해 보세요.
/account number [[:digit:]]+/
"계좌 번호" 뒤에 숫자가 일치하는 행만 처리하는지 확인하세요.match($0, "account number ([[:digit:]]+)", a)
패턴을 다시 찾아 일치하는 그룹의 위치와 길이( , 개수)를([[:digit:]]+)
배열에 저장합니다a
.print NR ";" substr($0, a[1, "start"], a[1, "length"])
기록번호 인쇄(즉줄 번호,FNR
여러 파일을 처리하는 경우 사용),;
첫 번째 그룹에 해당하는 하위 문자열: 시작 인덱스, 길이(패딩으로 채워짐 )a[1, "start"]
제공 .a[1, "length"]
match
이 모든 것은 행당 최대 하나의 계정이 있다고 가정합니다.
두 번째 변형은 $1
대신 인쇄합니다 NR
.즉파일의 첫 번째 필드는 전처리된 줄 번호입니다.
답변2
귀하의 grep 버전이 Perl 정규 표현식을 지원하는 경우, 뒤돌아보기를 사용할 수 있습니다:
grep -Pnio "(?<=account number.)([0-9]{0,15})" text
답변3
입력과 출력을 고려하면 awk 스크립트는 훨씬 간단해 보입니다.
gawk '/account number/ {
nr=gensub(/.*account\s*number\s*([0-9]+).*/, "\\1", "g")
print FNR "; " nr
}'
물론 계정 추출 및 출력 형식을 원하는 대로 조정해야 할 수도 있습니다. 그러나 당신은 요점을 이해합니다. (이 기능을 사용하려면 GNU awk가 필요합니다 gensub
.)
답변4
나는 이 목적으로 Perl을 사용하고 싶습니다. 다음과 같이 작동해야 합니다:
perl -ne 'print "$1; $2\n" if /^(\d+).*account number (\d+)/' input
^\d+
첫 번째 및 두 번째 캡처링 그룹(괄호 안의 부분, 여기서는 숫자)을 숫자( )로 시작하고 "계좌 번호"라는 문자열과 숫자가 포함된 줄에 인쇄합니다. Perl의 줄 번호 개념을 인쇄하려면 $.
대신 를 사용하십시오 $1
.