
我有一個這樣的文件:
id target_id length eff_length
1 intron_FBgn0000721:20_FBgn0000721:18 1136 243.944268
1 intron_FBgn0000721:19_FBgn0000721:18 1122 240.237419
2 intron_FBgn0264373:2_FBgn0264373:3 56 0
3 intron_FBgn0027570:4_FBgn0027570:3 54 0
對於第二列target_id
,我只想保留第一列和第二列FBgnXXXX
之間的字串(並非總是如此,有時是其他名稱)。因此,新的輸出檔案第 2 列的值將更簡單,但檔案的其餘部分保持不變。intron_
:
我嘗試使用 sed 命令,但不知道如何刪除我不需要的部分。
答案1
使用sed
和column
:
$ sed -E 's/ intron_([^:]*):[^[:space:]]*/ \1/' file | column -t
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
其中的關鍵部分是替換命令:
s/ intron_([^:]*):\S*/ \1/
它會尋找第一個冒號intron_
之後和之前的所有內容並將其保存intron_
到變數中1
。 [^[:space:]]*
匹配從冒號到字段末尾的所有內容。所有這些都被變數中保存的文字取代1
。
awk
與製表符分隔的輸出一起使用:
$ awk -v "OFS=\t" '{$2=$2;sub(/intron_/, "", $2); sub(/:.*/, "", $2); print}' file
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
解釋:
-v "OFS=\t"
這將輸出欄位分隔符號設定為製表符。這有助於排列列,但可能
column
沒有必要。$2=$2
列印一行時,
awk
不會變更為我們新指定的輸出欄位分隔符,除非我們更改該行上的某些內容。將第二個欄位指派給第二個欄位足以確保輸出具有製表符。sub(/intron_/, "", $2)
這
intron_
將從第二個字段中刪除。sub(/:.*/, "", $2)
這將從第二個欄位中刪除第一個冒號之後的所有內容。
print
這將列印我們的新行。
awk
與自訂列格式一起使用
這與上面的類似,但使用printf
這樣我們就可以根據需要自訂列寬和對齊方式的格式:
$ awk '{sub(/intron_/, "", $2); sub(/:.*/, "", $2); printf "%-3s %-12s %8s %3s\n",$1,$2,$3,$4}' file
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
這裡的語句printf "%-3s %-12s %8s %3s\n",$1,$2,$3,$4
以通常的樣式選擇列寬和對齊方式printf
。
使用sed
製表符分隔並將其轉換為逗號分隔
$ sed -E 's/ intron_([^:]*):[^[:space:]]*/ \1/; s/[[:space:]][[:space:]]*/,/g' file
id,target_id,length,eff_length
1,FBgn0000721,1136,243.944268
1,FBgn0000721,1122,240.237419
2,FBgn0264373,56,0
答案2
您可以使用perl
:
$ perl -anle '
BEGIN {$" = "\t"}
print "@{[@F]}" and next if $. == 1;
$F[1] = $1 if /_([^:]*):/;
print "@{[@F]}";
' file
id target_id length eff_length
1 FBgn0000721 1136 243.944268
1 FBgn0000721 1122 240.237419
2 FBgn0264373 56 0
3 FBgn0027570 54 0
解釋
-a
:自動將每一行分割成陣列@F
。BEGIN {$" = "\t"}
:我們將列表分隔符號設為 tab\t
,當在雙引號字串中插入數組或數組切片時使用它。print "@{[@F]}" and next if $. == 1
:我們列印標題,處理到下一行。$F[1] = $1 if /_([^:]*):/
_
:我們取得第一個 和之間的值:
,將其儲存到 中的第二個元素@F
。print "@{[@F]}"
:只需列印所需的輸出即可。
答案3
sed -e 'h;s/.*intron_[^:]*\(:[^[:space:]]*\).*/\1/;s/./ /g;;G;;s/\(.*\)\n\(.*\)intron_\([^:]*\):[^[:space:]]*/\2\3\1/' YourFile
在 1 sed(無管道)中保留列。它使用保持緩衝區
Posix 版本(--posix
GNU sed 也是如此)