フィールドから長さ n の数値を抽出し、文字列を返します。

フィールドから長さ n の数値を抽出し、文字列を返します。

テキストと数字の組み合わせを含むタブ区切りのファイルがあります。各行はそのまま維持したいのですが、5番目の列には6桁の数字しか存在しない場合はそのまま維持したいと思います。たとえば、

gene1   NM_033629   598G>A  P912    syndrome  1, 192315 syndrome 2,  225750 syndrome 3 610448   score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   syndrome 1 600195   score   AD  rec user    234567  Source

(症候群#は例として使用されており、任意のテキストである可能性があるため、検索して削除できるパターンではありません。)

私は出力が次のようになります:

gene1   NM_033629   598G>A  P912    192315 225750 610448    score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   600195  score   AD  rec user    234567  Source

6桁の数字を抽出する方法は4つありますが、それはできません。

ㅏ。元の行の数字を出力します。

b。編集されたフィールドを含む行全体を正常に印刷します。数値の抽出に使用するオプションは次のとおりです。

cat inputfile | cut -f 5 |grep -P '(? < !\d)\d{6}(?!\d)'
cat inputfile | cut -f 5 |grep -Po '(?< !\d)\d{6}(?!\d)'
cat inputfile | cut -f 5 |grep -o '[[:digit:]]*'
cat inputfile | cut -f 5 |grep -o "[0-9]\{6\}"

列にカットを使用するのが正しくないことを知っていますが、フィールド9にも6桁の数字があるので、抽出が正しいことを確認したいと思います。私はそれをすべて一緒に保つと主張します。どんな提案でもよろしくお願いします。

答え1

私が正しく理解したら、5番目の列はその中の6桁の数字をすべて空白で連結したいと思います。

おそらく:

perl -F'\t' -lape '
   $F[4] = join " ", grep {length == 6} ($F[4] =~ /\d+/g);
   $_ = join "\t", @F' < file

または、オペレーターに対する否定的なコメントを再利用してください。

perl -F'\t' -lape '
   $F[4] = join " ", ($F[4] =~ /(?<!\d)\d{6}(?!\d)/g);
   $_ = join "\t", @F' < file

そしてawk

awk -F'\t' -v OFS='\t' '
  {
    repl = sep = ""
    while (match($5, /[0-9]+/)) {
      if (RLENGTH == 6) {
        repl = repl sep substr($5, RSTART, RLENGTH)
        sep = " "
      }
      $5 = substr($5, RSTART+RLENGTH)
    }
    $5 = repl
    print
  }' < file

grepそれ自体は仕事には十分ではありません。grepパターンに一致する線を印刷するように設計されています。 GNU や ast-open などの一部の実装では、一致する行から文字列を抽出できますが、grepこれpcregrepは非常に制限的です。

特定の制限で機能できると考えられる唯一の++アプローチは、次のことを実装することcutです。greppastepcregrep grep

n='(?:.*?((?1)))?'
paste <(< file cut -f1-4) <(< file cut -f5 |
  pcregrep --om-separator=" " -o1 -o2 -o3 -o4 -o5 -o6 -o7 -o8 -o9 \
    "((?<!\d)\d{6}(?!\d))$n$n$n$n$n$n$n$n"
  ) <(< file cut -f6-)

各入力行には少なくとも6つのフィールドがあり、各フィールドの5番目のフィールドには1から9の6桁の数字があるとします。

答え2

awk '
BEGIN {
    FS = "\t";
    OFS = "\t";
}
{
    cnt = patsplit($5, arr, /[0-9]{6}/);
    $5 = arr[1];
    for(i = 2; i <= cnt; i++) {
        $5 = $5 " " arr[i];
    }
    print;
}' input.txt

patsplit(s, a [, r [, seps] ])- 分割文字列 S配列としてと区切り文字の配列9月正規表現についてアル字型、フィールド数を返します。 要素値は r と一致する s の一部です。

入力する:

gene1   NM_033629   598G>A  P912    syndrome 1, 192315 syndrome 2, 225750 syndrome 3 610448 score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   syndrome 1 600195   score   AD  rec user    234567  Source

出力:

gene1   NM_033629   598G>A  P912    192315 225750 610448    score   AD  hom user    123456  Source
gene2   NM_000459   613G>A  V115I   600195  score   AD  rec user    234567  Source

関連情報