awk/sed는 문자열에서 첫 번째와 마지막 대문자의 인덱스를 찾습니다.

awk/sed는 문자열에서 첫 번째와 마지막 대문자의 인덱스를 찾습니다.

다음과 같은 여러 문자열이 있습니다.

예시 문자열 1

--AbbbAnde---

예시 문자열 2

abksjiRNNBBKUGFLYFYLF

예시 문자열 3

-ankNUGUYUBUIGCafrg--

예시 문자열 4

BNKJUGFVULNK-Kew---

PS: 대문자가 0개 또는 1개 포함된 문자열이 없습니다.

수천 개의 파일이 있고 Python은 시간이 많이 걸리기 때문에 awk, sed 또는 다른 bash 프로그램을 통해 위의 예와 같은 문자열에서 첫 번째와 마지막 대문자의 인덱스를 찾고 싶습니다. 첫 번째 대문자의 색인은 처음부터 끝까지(왼쪽에서 오른쪽으로) 계산되어야 합니다. 그리고 마지막 대문자의 인덱스는 끝에서 시작(오른쪽에서 왼쪽)으로 계산되어야 합니다.

예를 들어,

예를 들어 string1의 경우 첫 번째 대문자는 A이고 인덱스는왼쪽에서 오른쪽으로(시작부터 끝까지). 마지막 대문자는 A이고 인덱스는7끝부터 처음까지.

예를 들어 string2의 경우 첫 번째 대문자는 R이고 인덱스는7왼쪽에서 오른쪽으로(시작부터 끝까지). 마지막 대문자는 F이고 인덱스는1끝부터 처음까지.

예를 들어 string3의 경우 첫 번째 대문자는 N이고 인덱스는5왼쪽에서 오른쪽으로(시작부터 끝까지). 마지막 대문자는 C이고 인덱스는7끝부터 처음까지.

예를 들어 string4의 경우 첫 번째 대문자는 B이고 인덱스는1왼쪽에서 오른쪽으로(시작부터 끝까지). 마지막 대문자는 K이고 인덱스는6끝부터 처음까지.

당신의 도움을 주셔서 감사합니다.

답변1

awk '
{
    start = match($0, /[A-Z]/)
    end   = match($0, /[A-Z][^A-Z]*$/)
    print (start ? start : "NaN"), (end ? length() - end + 1 : "NaN")
}' infile

답변2

$ awk '
    match($0,/[[:upper:]](.*[[:upper:]])?/) {
        print $0, RSTART, length()-(RSTART+RLENGTH-2)
    }
' file
xyzAb 4 2
--AbbbAnde--- 3 7
abksjiRNNBBKUGFLYFYLF 7 1
-ankNUGUYUBUIGCafrg-- 5 7
BNKJUGFVULNK-Kew--- 1 6

위의 내용은 이 입력에서 실행됩니다.

$ cat file
xyzAb
--AbbbAnde---
abksjiRNNBBKUGFLYFYLF
-ankNUGUYUBUIGCafrg--
BNKJUGFVULNK-Kew---

답변3

AWK를 사용하면 앞부분이나 뒷부분의 길이를 쉽게 얻을 수 있습니다. 질문에 표시된 색인을 얻으려면 1을 추가하십시오.

echo '--AbbbAnde---
abksjiRNNBBKUGFLYFYLF
-ankNUGUYUBUIGCafrg--
BNKJUGFVULNK-Kew---
foobarbaz' | awk '{

    printf("string %s\n", $0);
    head=tail=$0;

    sub(/[A-Z].*$/,"",head);
    sub(/^.*[A-Z]/,"",tail);

    printf("head <%s> %d\n", head, length(head)+1);
    printf("tail <%s> %d\n", tail, length(tail)+1);
}'

산출:

string --AbbbAnde---
head <--> 3
tail <nde---> 7
string abksjiRNNBBKUGFLYFYLF
head <abksji> 7
tail <> 1
string -ankNUGUYUBUIGCafrg--
head <-ank> 5
tail <afrg--> 7
string BNKJUGFVULNK-Kew---
head <> 1
tail <ew---> 6
string foobarbaz
head <foobarbaz> 10
tail <foobarbaz> 10

대문자가 포함되지 않은 입력을 처리하려면 스크립트를 확장해야 할 수도 있습니다. (이 질문은 이 경우 어떤 결과를 기대할 수 있는지 알려주지 않습니다.)

답변4

POSIX awk, 필드 구분 기호는 대문자 정규 표현식입니다.

LC_ALL=C \
awk -F '[A-Z]' '
NF>2{
  print length("x"$1), length("x"$NF)
}' file

Perl에는 각각 앞부분과 끝 부분에서 하위 문자열의 인덱스(0부터 시작)를 가져오는 index 및 rindex 내장 함수가 있습니다. 하지만 그 전에는 내장 인덱스가 정규식을 수행하지 않기 때문에 모든 대문자를 A로 변환합니다.

perl -lne '1 < tr/A-Z/A/ and
  print 1+index($_,"A"), $",
    length()-rindex($_,"A");
' file

확장된 정규식 모드(-E)를 사용하는 GNU sed

LC_ALL=C \
sed -E 'h;
  s/[A-Z].*/./
  :a
    s/./a/g;tb
    :b
      s/^a/c/
      s/([b-j])a/\u\1/
      y/BCDEFGHIJ/cdefghijk/
      s/ka/ab/
    tb
    y/bcdefghijk/0123456789/
    G;P
    /\n$/d
    z;x
    s/.*[A-Z]/./
  ba
' file | paste -d" " - -

산출:

3 7
7 1
5 7
1 6

관련 정보