awk/sed は、文字列の最初と最後の大文字のインデックスを探します。

awk/sed は、文字列の最初と最後の大文字のインデックスを探します。

次のようないくつかの文字列があります。

例ストリング1

--AbbbAnde---

例文字列2

abksjiRNNBBKUGFLYFYLF

例文字列3

-ankNUGUYUBUIGCafrg--

例ストリング4

BNKJUGFVULNK-Kew---

PS:大文字のゼロまたは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

関連情報