列のパターンで始まる情報のみを選択して別の列に印刷する方法

列のパターンで始まる情報のみを選択して別の列に印刷する方法

データファイルがありますA.tsv(フィールド区切り記号= \t)。

id  clade   mutation
243 40A S:ojo,L:juju,S:lili
254     
267 40B J:jijy,S:asel,M:ase

次のように、別の列(新しいファイルB.tsv)で始まる突然変異のみを印刷したいと思います。S:

id  clade   mutation    S_mutation
243 40A S:ojo,L:juju,S:lili S:ojo,S:lili
254     
267 40B J:jijy,S:asel,M:ase S:asel

awkでいくつかのコマンドを試しましたが、結果はありません。

awk -F '\t' 'BEGIN { OFS = FS } NR==1 {$(NF+1)="S_Mutation"} ; NR != 1 { $4 = ($3==^[Ss] ? $4 ) }; 1' A.tsv > B.tsv

何をすべきか知っていますか?ありがとう

答え1

これにより、POSIX awk図のように機能することができます。カンマ付きの3番目のフィールドを1より大きい行に分割し、S:で始まる要素を選択し、コンマで連結して最後の+1フィールドにします。

awk -F '\t' '
  BEGIN {
    OFS = FS
    _SEP_ = ","
  }

  NR==1{$(NF+1) = "S_mutation"}

  NR>1&&length($3)>0{
    nf = split($3, a, _SEP_)
    t = ""
    for (i=1; i<=nf; i++) {
      if (a[i] ~ /^S:/) {
        t = t (t=="" ? t : _SEP_) a[i]
      }
    }
    $(NF+1) = t
  }1
' file

同じPerlですが、正規表現を使うと

perl -lnse '$,="\t";
  print $_,($.==1?q(S_mutation):
  "@{[/(?:\t|,)\KS:[^,]*/g]}"||());
' -- -\"=, ./file

出力:

id   clade  mutation             S-mutation
243  40A    S:ojo,L:juju,S:lili  S:ojo,S:lili
254                              
267  40B    J:jijy,S:asel,M:ase  S:asel

答え2

(POSIX)を使用してくださいawk

awk -F "\t" '
BEGIN   { OFS = FS }
NR == 1 { $4 = "S_Mutation" }
NR  > 1 && NF == 3 {
    printf "%s", $0 "\t"
    $0 = $3
    gsub(/[^S]:[^,]*,?/, "")
    sub(/,$/, "")
    print $1
    next
}
1' data.txt
  • 行> 1、フィールド数= 3の場合
    • 改行なしで行を印刷します。
    • 行設定=フィールド3
    • 次の文字で始まらない文字列を削除します。S:
    • すべての末尾のカンマを削除してください。
    • 改行のあるフィールドの印刷
    • 次の行の処理
  • その他
    • 印刷ライン

$1[末尾]タブを印刷し、交換後に何もないことをテストしてから、TAB+フィールドを印刷したくありません。 (フィールドのない行に末尾のタブが必要ない場合S:xxx。例:

    # Print line
    printf "%s", $0
    # Set line = field 3
    $0 = $3
    # Replace all N:xxx where N is not S
    gsub(/[^S]:[^,]*,?/, "")
    # Remove trailing comma
    sub(/,$/, "")
    # Print the field
    if ($1 != "")
        print "\t"$1
    else
        print ""
    # Continue with next line
    next

答え3

パールを使う

perl -F'\t' -lpe '
    push @F, $. == 1 ? "S_mutation" : join ",", grep { /^S:/ } split /,/, $F[2];
    $_ = join "\t", @F
' A.tsv > B.tsv

前任者。

$ perl -F'\t' -lpe '
    push @F, $. == 1 ? "S_mutation" : join ",", grep { /^S:/ } split /,/, $F[2];
    $_ = join "\t", @F
' A.tsv | column -t
id   clade  mutation             S_mutation
243  40A    S:ojo,L:juju,S:lili  S:ojo,S:lili
254
267  40B    J:jijy,S:asel,M:ase  S:asel

答え4

使用しても問題ない場合は、以下を使用してくださいsed

sed 'h;s/.*[[:space:]]/,/;s/,[^S]:[^,]*//g;x;G;s/\n,/\t/'

\tGNUでのみ動作しますsed。他のスタイルでは、通常、ctrlvテキストタブは入力してTabキーを押して挿入されます。

概念は、行を予約済みスペースに保持してから最後の列を分離し、バリアント以外のすべてを削除することですS:。次に、保存された行の最後の列として追加します。

  • hその行を予約済みスペースにコピーします。
  • s/.*[[:space:]]/,/最後のタブまたはスペースの前の内容をコンマで置き換えます。したがって、最後の列を保持し、前にカンマを追加します。このコンマは次のステップで役に立ちます
  • s/,[^S]:[^,]*//gS:除外したすべての要素を削除します。
  • xアーカイブスペースとパターンスペースを交換して、アーカイブスペースGに保持されている元の列に新しい列を追加します。
  • s/\n,/\t/最後に、タブで導入された追加の改行文字とコンマを置き換えます。

関連情報