Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在匹配特定列时使用gsub_Bash_Awk_String Substitution - Fatal编程技术网

Bash 在匹配特定列时使用gsub

Bash 在匹配特定列时使用gsub,bash,awk,string-substitution,Bash,Awk,String Substitution,我有一个包含DNA碱基序列表的原始文件,带有行和列标签,还有一个单独的“位置”文件,列出了列标签的子集。我需要处理原始文件,对位置文件标识的列中的值执行转换 原始文件示例: name pos1 pos2 pos3 pos4 pos5 pos6 pos7 name1 AT TA CT GT CC TC TT name2 AA TA TT GT TC TC TT name3 AT TT CG AT CT TC TT name4 GT TA CT TT CC TC TT 示例位置文件: pos1 p

我有一个包含DNA碱基序列表的原始文件,带有行和列标签,还有一个单独的“位置”文件,列出了列标签的子集。我需要处理原始文件,对位置文件标识的列中的值执行转换

原始文件示例:

name pos1 pos2 pos3 pos4 pos5 pos6 pos7
name1 AT TA CT GT CC TC TT
name2 AA TA TT GT TC TC TT
name3 AT TT CG AT CT TC TT
name4 GT TA CT TT CC TC TT
示例位置文件:

pos1
pos3
pos6
pos7
在每个选定字段上,我需要执行以下转换:

A to T
C to G
G to C
T to A
因此,通过基于提供的位置文件处理示例原始文件而获得的输出将是:

name pos1 pos2 pos3 pos4 pos5 pos6 pos7
name1 TA TA GA GT CC AG AA
name2 TT TA AA GT TC AG AA
name3 TA TT GC AT CT AG AA
name4 CA TA GA TT CC AG AA
因此,第一行未被修改,在随后的每一行上,与列标签
pos1
pos3
pos6
pos7
对应的字段被转换,而其他字段保持不变


我知道如何使用
awk
应用
gsub()
来修改整个输入行或专门修改第n个字段,但我只需要修改位置文件中列出的字段,如数据文件第一行上的列标签所示。如何在
awk
中实现这一点?

假设不需要保留精确的字段(列)分隔符——也就是说,您可以自由地将每个列分隔符更改为固定字符串,例如单个空格——您可以在每个字段的基础上使用
gsub()
,然后重新构建记录。这解决了将更改限制到特定字段的问题

另一个问题是根据positions文件中的数据和列标题确定要修改的字段。有一种方法可以做到这一点:

  • 使用
    BEGIN
    块,从positions文件中读取每一行,并将其内容记录为数组索引。您可以将其视为在哈希表中记录每行的内容

  • 通过在字段上循环并检查标签数组中是否存在预读列标签,将预读列标签与从主输入的第一行读取的列标签相匹配。对于存在的字段,将字段号作为索引记录在第二个数组中

  • 对于后续的每一行,根据字段号是否记录为需要转换的字段之一,从其组成字段中重建记录,在原始值和修改值之间进行选择

  • 请特别注意,
    awk
    可以通过存储在变量中的字段号引用字段。因此,
    myfield=2;打印$myfield
    产生与打印$2相同的输出

一个
awk
程序,可以完成以下所有功能:

#!/usr/bin/awk

function baseswap(seq) {
  gsub(/A/, "X", seq)
  gsub(/T/, "A", seq)
  gsub(/X/, "T", seq)
  gsub(/C/, "X", seq)
  gsub(/G/, "C", seq)
  gsub(/X/, "G", seq)
  return seq
}

BEGIN  {
         while ((getline < "positions") == 1) {
           labels[$1] = 1
         }
       }

FNR==1 {
          for (i = 2; i <= NF; i++) {
            if (labels[$i]) {
              fields[i] = 1
            }
          }
          print
          next
       }

       {
         record = $1
         for (i = 2; i <= NF; i++) {
           record = record " " (fields[i] == 1 ? baseswap($i) : $i)
         }
         print record
       }
#/usr/bin/awk
功能基本交换(seq){
gsub(/A/,“X”,序号)
gsub(/T/,“A”,序号)
gsub(/X/,“T”,序号)
gsub(/C/,“X”,序号)
gsub(/G/,“C”,序号)
gsub(/X/,“G”,序号)
返回顺序
}
开始{
而((getline<“positions”)==1){
标签[$1]=1
}
}
FNR==1{

对于(i=2;i假设没有必要保留精确的字段(列)分隔符——也就是说,您可以自由地将每个列分隔符更改为固定字符串,例如单个空格——您可以使用
gsub()
以每个字段为基础,然后重新构建记录。这样可以解决将更改限制到特定字段的问题

另一个问题是根据positions文件中的数据和列标题确定要修改的字段。以下是一种方法:

  • 使用
    BEGIN
    块,从positions文件中读取每一行,并将其内容记录为数组索引。您可以将其视为在哈希表中记录每一行的内容

  • 将预读列标签与从主输入的第一行读取的列标签相匹配,方法是在字段上循环并检查它们是否存在于标签数组中。对于存在的字段,将字段编号作为索引记录在第二个数组中

  • 对于后续的每一行,根据字段号是否记录为需要转换的字段之一,从其组成字段中重建记录,在原始值和修改值之间进行选择

  • 请特别注意,
    awk
    可以通过存储在变量中的字段编号引用字段。因此,
    myfield=2;print$myfield
    产生与
    print$2
    相同的输出

一个
awk
程序,可以完成以下所有功能:

#!/usr/bin/awk

function baseswap(seq) {
  gsub(/A/, "X", seq)
  gsub(/T/, "A", seq)
  gsub(/X/, "T", seq)
  gsub(/C/, "X", seq)
  gsub(/G/, "C", seq)
  gsub(/X/, "G", seq)
  return seq
}

BEGIN  {
         while ((getline < "positions") == 1) {
           labels[$1] = 1
         }
       }

FNR==1 {
          for (i = 2; i <= NF; i++) {
            if (labels[$i]) {
              fields[i] = 1
            }
          }
          print
          next
       }

       {
         record = $1
         for (i = 2; i <= NF; i++) {
           record = record " " (fields[i] == 1 ? baseswap($i) : $i)
         }
         print record
       }
!/usr/bin/awk
功能基本交换(seq){
gsub(/A/,“X”,序号)
gsub(/T/,“A”,序号)
gsub(/X/,“T”,序号)
gsub(/C/,“X”,序号)
gsub(/G/,“C”,序号)
gsub(/X/,“G”,序号)
返回顺序
}
开始{
而((getline<“positions”)==1){
标签[$1]=1
}
}
FNR==1{
对于(i=2;i
$cat tst.awk
开始{
拆分(“A T C G C T A”,T)
对于(i=1;t中的i;i+=2){
map[t[i]]=t[i+1]
}
}
NR==FNR{
fldNames[$1]
下一个
}
FNR==1{
对于(i=1;i1{
$0=tolower($0)
用于(目标中的fldNr){
用于(地图中的旧版本){
gsub(tolower(旧版),map[旧版],$fldNr)
}
}
$0=toupper($0)
}
{print}
$awk-f tst.awk原始位置
名称pos1 pos2 pos3 pos4 pos5 pos6 pos7
名称1 TA TA GA GT CC AG AA
名称2 TT TA AA GT TC AG AA
名称3 CT AG AA处的TA TT GC
名称4 CA TA GA TT CC AG AA
$cat tst.awk
开始{
拆分(“A T C G C T A”,T)
对于(i=1;t中的i;i+=2){
map[t[i]]=t[i+1]
}
}
NR==FNR{
fldNames[$1]
下一个
}
FNR==1{
对于(i=1;i1{
$0=tolower($0)
用于(目标中的fldNr){
用于(地图中的旧版本){
gsub(tolower(旧版),map[旧版],$fldNr)
}
}
$0=toupper($0)
}
{print}
$awk-f tst.awk原始位置
名称pos1 pos2 pos3 pos4 pos5 pos6 pos7
名称1 TA TA GA GT CC AG AA
名称2 TT TA AA GT TC AG AA
名称