String 利用Awk提取信息

String 利用Awk提取信息,string,awk,String,Awk,这篇文章与我之前关于字符串拆分的问题有关:。假设我们有以下字符串: 1A5T4 此字符串对以下信息进行编码: 位置2处的A(A前1项) 位置8处的T(T之前的7项,即1+A+5) 最右边的字母后面没有更多的字母意味着没有更多的相关信息可提取 因此,这里需要的输出是a28 我想编写Awk脚本来获取这些信息,最好是两个数组:一个包含位置,另一个包含字母。我认为这将是一种方便的存储方式,因为我需要使用我正在编写的脚本的其他部分中的值(或者更确切地说,我正在努力编写) 我认为第一步应该是通过拆分字符串

这篇文章与我之前关于字符串拆分的问题有关:。假设我们有以下字符串:

1A5T4
此字符串对以下信息进行编码: 位置2处的A(A前1项) 位置8处的T(T之前的7项,即1+A+5) 最右边的字母后面没有更多的字母意味着没有更多的相关信息可提取

因此,这里需要的输出是
a28

我想编写Awk脚本来获取这些信息,最好是两个数组:一个包含位置,另一个包含字母。我认为这将是一种方便的存储方式,因为我需要使用我正在编写的脚本的其他部分中的值(或者更确切地说,我正在努力编写)

我认为第一步应该是通过拆分字符串来划分字符串的界限(这要归功于有帮助的评论者)

但可能不需要分隔符。我尝试使用for循环完成这项任务,通过迭代连续的字母-数字对,并将它们添加到数组中。但是,我无法使其工作(没有阵列,因为我无法使循环正常工作):

A为2(如上例所示) T是11(2+2+3(插入符号后CCG中的字母之和)+3,因此T之前有10个位置)

因此,这里需要的输出是
a211

插入符号后面的字母与其他任何内容无关,除了将字母的索引转换为插入符号块的速率

如果能得到一些关于如何解决这个问题的有用提示,那就太好了

说明:脚本应该输出所有字母,只要它们前面没有插入符号。插入符号后的字母仅移动索引。例如:

27T19T^A16G8G29
应该给

 T T G G 28 48 66 75
 T T G G 28 48 65 74

应该给

 T T G G 28 48 66 75
 T T G G 28 48 65 74
更新:

多亏了@vgersh99,我成功地改进了代码。它首先将每个块后面的文本块转换为与其他块相同的格式。然后以相同的方式处理所有块(
for
loop),最后,插入符号值不显示(if语句)。但是,如果存在多个长度可变的插入符号块,则仍然存在问题

1A5T4
1A1^AAAAA2T2
1A2^CCG3T4
27T19T^A16G8G29
27T19T16G8G29
1A^AA5^TT4T4
10A3A1G9A10A25^TT1^G1^G42T12^G1G29

{
  match($0, /\^[A-Z]+/);
  a = "^"length(substr($0, RSTART, RLENGTH))-2"^";
  gsub(/\^[A-Z]+/, a)
}
# if a letter is directly followed by a caret, such carets are removed, as they would have count==0
{
  a = match($0, /[A-Z]+\^/);
  a = substr($0, RSTART, RLENGTH-1);
  gsub(/[A-Z]+\^/, a)
}
# intermediate string with transformed caret blocks is then used further
  {
      sum=0; delete(out); str=""
      n=patsplit($0,b, /[[:alpha:]^]/, seps);
      for(i=1; i<=n;i++) {
        sum+=seps[i-1]+1
        # print b[i], sum
        if (b[i]!="^")
        {out[sum]=b[i]}
      }

    PROCINFO["sorted_in"] = "@ind_num_asc"
    for(i in out) {
      printf("%s ", out[i])
      str=(str? str OFS:"") i
  }

      print str
    } tst.txt

A T 2 8
A T 2 12
A T 2 12
T T G G 28 48 66 75
T T G G 28 48 65 74
A T 2 17
A A G A A T G 11 15 17 27 38 117 134

%echo 1A5T4|gawk'BEGIN{FS=“”}{for(i=1;i=“A”){s=s$i}{else{for(j=1;j
%echo 1A5T4|gawk'BEGIN{FS=“”}{for(i=1;i=“A”){s=s$i}{else{for(j=1;j这是一个粗略的近似值,因为我对你的解释有点困惑。。。
可能需要稍微调整一下。。。
通过使用gawk对
patsplit
PROCINFO[“sorted_in”]
的支持,实现是特定于
gawk的

给定
myFile.txt

1A5T4
1A1^AAAAA2T2
1A2^CCG3T4
27T19T^A16G8G29
27T19T16G8G29
1A^AA5^TT4T4
10A3A1G9A10A25^TT1^G1^G42T12^G1G29
$cat tst.awk
#以下“核心”模块的准备模块
{
#如果插入符号后面跟字母,则用插入符号后面跟字母的长度来代替
#字母字符串(-1)后跟插入符号
#例如:1A1^AAAA2T2->1A1^4^2T2
#$0=gensub(/\^([:alpha:]+)/,“^”长度(“\\2”)-2“^”,“G”)
if(匹配($0,/\^([:alpha:]+)/,子1))
for(i=1;子1中的i;i++)
sub(sub1[i],int(sub1[i,“长度”])-1“^”)
#如果一个字母后面紧跟着一个插入符号,这样的插入符号就会被删除,因为它们的count==0
$0=gensub(/([:alpha:]])\^/,“\\1”,“G”)
#打印“[“$0”]”
#下一个
}
#“核心”模块
#然后进一步使用带有转换插入符号块的中间字符串
{
sum=0;删除(out);str=“”
n=patsplit($0,b,/[:alpha:://seps)];

对于(i=1;i这是一个粗略的近似值,因为我对你的解释有点困惑。。。 可能需要稍微调整一下。。。 通过使用gawk对
patsplit
PROCINFO[“sorted_in”]
的支持,实现是特定于
gawk的

给定
myFile.txt

1A5T4
1A1^AAAAA2T2
1A2^CCG3T4
27T19T^A16G8G29
27T19T16G8G29
1A^AA5^TT4T4
10A3A1G9A10A25^TT1^G1^G42T12^G1G29
$cat tst.awk
#以下“核心”模块的准备模块
{
#如果插入符号后面跟字母,则用插入符号后面跟字母的长度来代替
#字母字符串(-1)后跟插入符号
#例如:1A1^AAAA2T2->1A1^4^2T2
#$0=gensub(/\^([:alpha:]+)/,“^”长度(“\\2”)-2“^”,“G”)
if(匹配($0,/\^([:alpha:]+)/,子1))
for(i=1;子1中的i;i++)
sub(sub1[i],int(sub1[i,“长度”])-1“^”)
#如果一个字母后面紧跟着一个插入符号,这样的插入符号就会被删除,因为它们的count==0
$0=gensub(/([:alpha:]])\^/,“\\1”,“G”)
#打印“[“$0”]”
#下一个
}
#“核心”模块
#然后进一步使用带有转换插入符号块的中间字符串
{
sum=0;删除(out);str=“”
n=patsplit($0,b,/[:alpha:://seps)];
对于(i=1;i可以试试这个

{mawk/mawk2/gawk} 'BEGIN {  FS = "[=]+"; 
                           OFS =  "="; 
    } {
        outC = outP = pos = ""; 

        gsub(/\^/,          "=&" );   # first split carets next to letters
        gsub(/[0-9]+/,      "=&=");   # insert delims around numbers
         
    } { $1 = $1 } {

        while (match($0, /[\^][A-Z]+/)) { sub(/[\^][A-Z]+/, RLENGTH -1) } 
    } { 
        x = 1; do { 
             
           if ($(x) ~ /[0-9]+|^$/) { pos += int($(x)) } else { 

              outC = outC ""  $(x) " "; 
              outP = outP "" ++pos " "; 
      
        } } while (++x <= NF); print outC outP; } ' 
{mawk/mawk2/gawk}开始{FS=“[=]+”;
OFS=“=”;
} {
outC=outP=pos=“”;
gsub(/\^/,“=&”)#字母旁边的第一个拆分插入符号
gsub(/[0-9]+/,“=&=”)#在数字周围插入delims
} { $1 = $1 } {
而(匹配($0,/[\^][A-Z]+/){sub(/[\^][A-Z]+/,RLENGTH-1)}
} { 
x=1;do{
if($(x)~/[0-9]+|^$/){pos+=int($(x))}else{
outC=outC“$(x)”;
输出=输出“++位置”;
}}虽然(++x可以试试这个

{mawk/mawk2/gawk} 'BEGIN {  FS = "[=]+"; 
                           OFS =  "="; 
    } {
        outC = outP = pos = ""; 

        gsub(/\^/,          "=&" );   # first split carets next to letters
        gsub(/[0-9]+/,      "=&=");   # insert delims around numbers
         
    } { $1 = $1 } {

        while (match($0, /[\^][A-Z]+/)) { sub(/[\^][A-Z]+/, RLENGTH -1) } 
    } { 
        x = 1; do { 
             
           if ($(x) ~ /[0-9]+|^$/) { pos += int($(x)) } else { 

              outC = outC ""  $(x) " "; 
              outP = outP "" ++pos " "; 
      
        } } while (++x <= NF); print outC outP; } ' 
{mawk/mawk2/gawk}开始{FS=“[=]+”;
OFS=“=”;
} {
outC=outP=pos=“”;
gsub(/\^/,“=&”)#字母旁边的第一个拆分插入符号
gsub(/[0-9]+/,“=&=”)#在数字周围插入delims
} { $1 = $1 } {
而(匹配($0,/[\^][A-Z]+/){sub(/[\^][A-Z]+/,RLENGTH-1)}
} { 
x=1;do{
if($(x)~/[0-9]+|^$/){pos+=int($(x))}else{
outC=outC“$(x)”;
输出=输出“++位置”;

}}虽然(++x谢谢,我确实应该更清楚。我修正了这个问题,添加了所需的输出。@LechKaczmarczyk,我在OP中没有看到任何“所需的输出”更改。你能接受提供的吗
1A5T4
1A1^AAAAA2T2
1A2^CCG3T4
27T19T^A16G8G29
27T19T16G8G29
1A^AA5^TT4T4
10A3A1G9A10A25^TT1^G1^G42T12^G1G29
$ cat tst.awk
# prep block for the following "core" mod block
{
   # if a caret is followed by letters, subsitute it by caret followed by the length of
   # the letter string (-1) followed by a caret
   # eg: 1A1^AAAAA2T2 -> 1A1^4^2T2
   #$0=gensub(/\^([[:alpha:]]+)/,"^" length("\\2")-2 "^","G")
   if(match($0,/\^([[:alpha:]]+)/,sub1))
           for (i=1;i in sub1;i++)
               sub(sub1[i],int(sub1[i,"length"])-1 "^")

   # if a letter is directly followed by a caret, such carets are removed, as they would have count==0
   $0=gensub(/([[:alpha:]])\^/,"\\1","G")
   #print "[" $0 "]"
   #next
}

# "core" mod block
# intermediate string with transformed caret blocks is then used further
{
      sum=0; delete(out); str=""
      n=patsplit($0,b, /[[:alpha:]^]/, seps);
      for(i=1; i<=n;i++) {
        sum+=seps[i-1]+1
        # print b[i], sum
        if (b[i]!="^")
        {out[sum]=b[i]}
      }

    PROCINFO["sorted_in"] = "@ind_num_asc"
    for(i in out) {
      printf("%s ", out[i])
      str=(str? str OFS:"") i
  }
  print str
}
$ gawk -f tst.awk myFile.txt
A T 2 8
A T 2 12
A T 2 12
T T G G 28 48 66 75
T T G G 28 48 65 74
A T T T 2 11 12 17
A A G A A G G T G G 11 15 17 27 38 69 72 115 129 131
{mawk/mawk2/gawk} 'BEGIN {  FS = "[=]+"; 
                           OFS =  "="; 
    } {
        outC = outP = pos = ""; 

        gsub(/\^/,          "=&" );   # first split carets next to letters
        gsub(/[0-9]+/,      "=&=");   # insert delims around numbers
         
    } { $1 = $1 } {

        while (match($0, /[\^][A-Z]+/)) { sub(/[\^][A-Z]+/, RLENGTH -1) } 
    } { 
        x = 1; do { 
             
           if ($(x) ~ /[0-9]+|^$/) { pos += int($(x)) } else { 

              outC = outC ""  $(x) " "; 
              outP = outP "" ++pos " "; 
      
        } } while (++x <= NF); print outC outP; } '