Мне нужна помощь с bash в Linux; Мне нужно найти команду, которая выполняет следующую операцию.
У меня есть файл, в котором поля разделены символом | символ, и я должен выбрать значения, которые появляются после 51 вхождения этого символа и до появления следующего.
Эта команда bash, если ее применить к следующему файлу, вернет/выберет только значение 0,02468
Образец файла:
AB=0.543;AC=1;AF=0.5;AN=1;BaseQRankSum=-8.244;DB;DP=178;DS;Dels=0;FS=0.568;GC=36;HRun=0;HaplotypeScore=3.5479;MQ=59.09;MQ0=0;MQRankSum=-1.171;QD=12.69;ReadPosRankSum=-0.923;SB=-1203.97;SBD=0.83;VQSLUD=7.2941;culprit=MQRankSum;set=GGSKSNP;CSQ=C|missense_variant|MODERATE|SLC7A2|ENSG00000003487|Transcript|ENST00000001234|protein_coding|7/8||ENST00000001234.10:c.1223G>C|ENSP00000001234.10:p.Cys416Ser|1234|1234|123|C/S|tGt/tCt|rs1234567||1||SNV|HGNC|123456|YES|||CCDS12345.1|ENSP00000004531|P52569||UPI1234A123A4||Ensembl|G|G|||tolerated(0.41)|benign(0)|Pfam_domain:PF12345&hmmpanther:PTHR12345&hmmpanther:PTHR12345:SF242&TIGRFAM_domain:TIGR00906|||0.0613|0|0.0202|0.2421|0|0.0501|0.0006809|0.0003488|0.02468|
Может ли кто-нибудь помочь мне с этой командой bash? Я попытался найти его в Интернете, но ничего не нашел.
Используйте cut
. Он используется, ну, чтобы "разрезать" строку между разделителями. Бывший:
cut -d"|" -f52 <<EOF
AB=0.543;AC=1;AF=0.5;AN=1;BaseQRankSum=-8.244;DB;DP=178;DS;Dels=0;FS=0.568;GC=36;HRun=0;HaplotypeScore=3.5479;MQ=59.09;MQ0=0;MQRankSum=-1.171;QD=12.69;ReadPosRankSum=-0.923;SB=-1203.97;SBD=0.83;VQSLUD=7.2941;culprit=MQRankSum;set=GGSKSNP;CSQ=C|missense_variant|MODERATE|SLC7A2|ENSG00000003487|Transcript|ENST00000001234|protein_coding|7/8||ENST00000001234.10:c.1223G>C|ENSP00000001234.10:p.Cys416Ser|1234|1234|123|C/S|tGt/tCt|rs1234567||1||SNV|HGNC|123456|YES|||CCDS12345.1|ENSP00000004531|P52569||UPI1234A123A4||Ensembl|G|G|||tolerated(0.41)|benign(0)|Pfam_domain:PF12345&hmmpanther:PTHR12345&hmmpanther:PTHR12345:SF242&TIGRFAM_domain:TIGR00906|||0.0613|0|0.0202|0.2421|0|0.0501|0.0006809|0.0003488|0.02468|
EOF
выведет ожидаемое.
Ниже приведены некоторые другие часто используемые команды для такой проблемы.
Мы можем использовать awk
:
awk -vFS = "|" '{print $52}'
Мы можем прочитать строку в массив и вывести значение 51:
IFS = "|" read -r -a arr
echo "${arr[51]}"
Мы можем использовать read, чтобы пропустить первые 51 значение, например:
IFS = "|" read -r _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ val _
echo "$val"
В последнем примере всего 50 _
, но, что более важно, вам нужен дополнительный _
после val
, иначе после него будет собираться мусор.
Вы можете использовать sed -E
:
sed -E "s:^([^\|]*\|){51}([^\|]*).*$:\2:"
В качестве альтернативы вы можете использовать чистый BASH:
read temp
for i in {1..51}; do
temp = "${temp#*|}"
done
echo "${temp%%|*}"
awk
, IFS
и cut
подходы приведены выше.
Лично я согласен с тем, что cut
должен быть победителем, потому что его гораздо проще запомнить, чем любой другой метод, указанный в теме.
Следуя совету Эда Мортона.
Самый простой и элегантный подход awk
:
awk -F'|' '{print $52}'
-F'|'
заставит разделитель полей по умолчанию быть символом |
.
'{print $52}'
печатать поле номер 52.
Еще один странный способ с sed
:
sed 's/|[^|]*//52g;s/.*|//'
-vFS = "|"
(без пробела после-v
) предназначен только для зевак. Измените его на-v FS = "|"
, и он будет работать в любом awk. Сказав это, вы должны просто сделать-F'|'
вместо этого также в любом awk.