我一直試圖在一個如下所示的 fasta 檔案中找到每個物種的 1 數量:
>111
1100101010
>102
1110000001
所需的輸出將是:
>111
5
>102
4
我知道如何獲取檔案中 1 的數量:
grep -c 1 file
我的問題是我找不到跟蹤每個物種的 1 數量(而不是檔案中的總數)的方法。
uj5u.com熱心網友回復:
grep -c 1會給你匹配行的數量,而不是 s 的總數1。您可以使用grep -o使其僅在單獨的行上列印每個匹配行的匹配部分,然后wc -l計算行數。
while read -r line
do
if [[ ${line:0:1} == '>' ]]; then
if [[ -n $count ]]; then
printf "%d\n" $count
fi
count=0
echo "$line"
else
((count = $(grep -o 1 <<< "$line" | wc -l)))
fi
done < fasta_file
if [[ -n $count ]]; then
printf "%d\n" $count
fi
或者純粹的重擊使用引數擴展:
while read -r line
do
if [[ ${line:0:1} == '>' ]]; then
if [[ -n $count ]]; then
printf "%d\n" $count
fi
count=0
echo "$line"
else
line="${line//[^1]/}" # remove everything but 1's
((count = ${#line})) # add the length of line to count
fi
done < fasta_file
if [[ -n $count ]]; then
printf "%d\n" $count
fi
類似的設定perl:
open my $fh, 'fasta_file' or die "$!";
my $count=-1;
while(<$fh>) {
if(/^>/) {
print "$count\n" unless($count == -1);
$count = 0;
print;
} else {
$count = tr/1//;
}
}
print "$count\n" unless($count == -1);
close $fh;
音譯運算子 ,tr///將回傳它執行了多少音譯,因為1它是唯一的引數,所以它與 count 相同1。
uj5u.com熱心網友回復:
>111
11001010101110000001
也可以寫成
>111
1100101010
1110000001
但現有的解決方案都不適用于后者。這解決了這種疏忽:
perl -Mv5.10 -ne'
if ( /^>/ ) {
say $c if defined $c;
$c = 0;
print;
} else {
$c = tr/1//;
}
END {
say $c if defined $c;
}
' file.fasta
對于上面顯示的兩個檔案,程式輸出
>111
9
uj5u.com熱心網友回復:
一個awk想法:
awk '
/^>/ { print ; next } # print lines starting with ">"; skip to next input line
{ print gsub(/1/,"x") } # replace all "1" characters with dummy "x"; gsub() returns number of replacements (ie, number of "1" characters in the line)
' file
或作為單行:
awk '/^>/ {print;next} {print gsub(/1/,"x")}' file
折疊成三元運算子以確定要做什么print:
awk '{print ($0 ~ /^>/ ? $0 : gsub(/1/,"x"))}' file
這些都產生:
>111
5
>102
4
uj5u.com熱心網友回復:
假設您的 fasta 已按照您的指示進行格式化,并假設 usingawk是可以接受的,那么以下方法可能會起作用:
while read -r one ; do
echo "${one}"
read -r two
awk -F"1" '{print NF-1}' <<< "${two}"
done <fasta.txt
(注意:awk 命令將字串除以 '1',然后列印結果欄位數減 1)
fasta.txt:
>111
1100101010
>102
1110000001
輸出:
>111
5
>102
4
根據@ikegami,如果記錄分布在多行:
#!/bin/bash
fasta_file="${1:-fasta2.txt}"
while read -r line ; do
if [[ "$line" =~ ^\>.* ]]; then
[[ -n "${cnt}" ]] && echo "${cnt}"
cnt=0
echo "${line}"
else
((cnt = $(awk -F"1" '{print NF-1}' <<< "${line}") ))
fi
done <"${fasta_file}"
[[ -n "${cnt}" ]] && echo "${cnt}"
uj5u.com熱心網友回復:
這是gnu-awk也適用于多行記錄的解決方案:
cat file
>111
11001
01010
>102
1110000001
awk -v RS='>[0-9] \n' 'NF {printf ORS "%s\n", gsub(/1/, "&")} {ORS=RT}' file
>111
5
>102
4
uj5u.com熱心網友回復:
mawk -F1 '$ !NF=NF - NF^/^[>]/'
gawk -F1 '$_=NF-NF ^/^>/' # that's the most succinct
# vers. I could conjure up
>111
1100101010
>102
1110000001
5
4
如果你真的想要其他 2 行::
gawk -F1 '/^>/ || $_=--NF'
mawk -F1 '/^>/ || $!_=$_=--NF'
>111
1100101010
>102
1110000001
1 >111
2 5
3 >102
4 4
如果你需要多行的:
gawk '$_ = sprintf("%.*s%.*s\n%.f",/^[^>]/,">", (__= index($_,ORS) ) - FS, $_,
NF-FS-substr("",__=substr($_,FS,__))-gsub(FS,"",__))' RS='\n[>]' FS=1
|
>111
9
uj5u.com熱心網友回復:
使用您顯示的示例,請嘗試以下awk代碼。用 GNU 撰寫和測驗awk,應該可以在任何awk.
awk '/^>/{print;next} {print (NF?split($0,arr,"1")-1:0)}' Input_file
解釋:簡單的解釋是,檢查條件是否從行開始,>然后列印該行next并將跳過此處的所有進一步陳述句。然后使用print檢查是否NF為 NOT NULL 的函式,然后使用split函式將當前行拆分為陣列 arr 并帶有分隔符1(這將提供當前行中存在的 1 的數量,這樣做-1將給出準確的計數),ELSENF不為 NULL 然后列印0(對于 EMPTY行)。
uj5u.com熱心網友回復:
要在單個實體下處理一個標題上的多行資料awk-
$: cat fasta.txt
>101
1100101010
1111111010
1100000000
>102
1110000001
>103
1100000000
1110000001
$: awk '/^>/{if(NR>1){print cnt;} print; cnt=0;} /^[01]/{ cnt =gsub(/1/,""); } END{print cnt;}' fasta.txt
>101
15
>102
4
>103
6
不像這里的其他版本那樣優雅,但可能更容易閱讀和理解。YMMV。
uj5u.com熱心網友回復:
$ awk '!/>/{split($0,a,"");$0=0;for(i in a)$0 =a[i]}1' fasta.txt
>111
5
>102
4
$ awk '!/>/{for(i=sum=0;i <length;)sum =substr($0,i,1);$0=sum}1' fasta.txt
>111
5
>102
4
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/494026.html
