Как я могу поместить команду sed в цикл while?

#unix #sed

Вопрос:

Надеюсь, кто-нибудь добрый сможет мне помочь, пожалуйста!

У меня есть файл input.list :

 /scratch/user/IFS/IFS001/IFS003.GATK.recal.bam
/scratch/user/IFS/IFS002/IFS002.GATK.recal.bam
/scratch/user/EGS/ZFXHG22/ZFXHG22.GATK.recal.bam
 

и я хочу извлечь бит раньше .GATK.recal.bam — я нашел решение для этого:

 sed 's/.GATK.recal.bam.*//' input.list | sed 's@.*/@@' 
 

Теперь я хочу включить это в цикл while, но это не работает… пожалуйста, может кто-нибудь взглянуть и указать мне, где я делаю что-то не так. Моя попытка приведена ниже:

 while read -r line; do ID=${sed 's/.GATK.recal.bam.*//' $line | sed 's@.*/@@'}; sbatch script.sh $ID; done < input.list
 

Приносим извинения за легкую Q…

Комментарии:

1. $line это не файл. $() Не используйте ${} . Цитируйте использование переменных: "$line" , "$ID" , и т.д. Вы также можете использовать один sed без использования while: <input.list sed -e 's/.GATK.recal.bam.*//' -e 's@.*/@@' | xargs -I@ sbatch script.sh @

2. unix.stackexchange.com/questions/169716/…

Ответ №1:

Вы можете использовать выходные sed данные команды в качестве входных данных для цикла:

 sed 'COMMAND' input.file | while read -r id ; do
    some_command "${id}"
done
 

Вместо петли также xargs можно использовать:

 sed 'COMMAND' input.file | xargs -n1 some_command
 

ps: GNU sed поддерживает выполнение результата s операции в виде команды. Я бы не рекомендовал использовать это в производстве, по крайней мере, по соображениям переносимости, но, вероятно, об этом стоит упомянуть:

 sed 's/(.*).GATK.recal.bam.*/sbatch script.sh 1/e' input.file
 

Ответ №2:

Вы можете сделать это прямо bash (если вы используете эту оболочку; ksh93 и zsh будет очень похоже), не sed требуется:

 while read -r line; do
    id="${line##*/}" # Remove everything up to the last / in the string
    id="${id%.GATK.recal.bam}" # Remove the trailing suffix
    sbatch script.sh "$id"
done < input.list
 

По крайней мере, вы можете использовать один sed звонок на линию:

 id=$(sed -e 's/.GATK.recal.bam$//' -e 's@.*/@@' <<<"$line")
 

или с простым sh

 id=$(printf "%sn" "$line" | sed -e 's/.GATK.recal.bam$//' -e 's@.*/@@')