Text-Processing

從欄位中提取長度為 n 的數字並返回字元串

  • October 12, 2017

我有一個包含文本和數字組合的製表符分隔文件。我想保持每一行不變,但我只想保留第 5 列中的六位數字(如果存在)。例如:

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

(以 Syndrome # 為例,它可以是任何文本,所以不是我可以搜尋和刪除的模式)

我希望輸出為:

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

我有 4 種方法來提取 6 位數字,但是,我不能

一種。輸出它起源的行中的數字

灣。使用一個已編輯的欄位成功列印整行。我用來提取數字的選項是:

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\}"

我知道對列使用 cut 是不正確的,但我想確保我的提取正確,因為欄位 9 中還有一個六位數。我一直堅持把這些放在一起。在此先感謝您的任何建議

如果我理解正確,您希望第 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++方法是實現greppaste``pcregrep 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 位數字。

引用自:https://unix.stackexchange.com/questions/397510