2014-07-03 3 views
-1

У меня есть этот мир кода:СЭД - команда незакрытых `S'

cat BP.csv | while read line ; do 
    goterm=$(awk '{print $1}') ; 
    name=$(awk '{print $2}') ; 
    grep -w "$goterm" GOEA.csv | sed "s/$goterm/pi/g" ; 
done 

файл BP.csv имеет следующий формат:

GO:0008283 cell proliferation 
GO:0009405 pathogenesis 
GO:0010201 response to continuous far red light stimulus by the high-irradiance response system 
GO:0009641 shade avoidance 

в то время как GOEA.csv имеет следующий формат:

4577 GO:0006807 0.994 2014_06_01 
4577 GO:0016788 0.989 2014_06_01 
4577 GO:0043169 0.977 2014_06_01 
4577 GO:0043170 0.963 2014_06_01 

sed не работает. Я хочу изменить GO:0043170, например, в строке «пи», но это дает:

sed: -e expression #1, char 12: unterminated `s' command 

Почему? Спасибо.

+2

Какова ценность goterm? –

+0

@ Авинаш Радж, правда? Разве вы не видите, что geterm является первым столбцом файла BP.csv? – user2979409

+1

Ick, вы понимаете, что эти две команды 'awk' считываются из' stdin', а не из переменной '$ line', правильно? – ams

ответ

3

Вы работаете вашу команду awk против без входа, Попробуйте это:

cat BP.csv | while read line ; do 
    goterm=$(awk '{print $1}' <<< "$line") ; 
    name=$(awk '{print $2}' <<< "$line") ; 
    grep -w "$goterm" GOEA.csv | sed "s/$goterm/pi/g" ; 
done 
+1

+1. awk на самом деле выполнялся против stdin, поэтому '$ goterm' содержал список строк, разделенных строкой, из первых значений столбца из строки 2 и далее. Так как выражение 's' тогда имело безвозвратный литеральный канал в середине, sed сказал, что он был истреблен. –

+0

@thatotherguy вы правы, иначе awk зависает, ожидая ввода. – Tiago

0

Я бы реструктурировать, что все это больше похоже на это:

while read goterm restofline 
do 
    grep -w "${goterm}" GOEA.csv | sed -e "s/${goterm}/pi/g" 
done < BP.csv 

Нет причины для awk вещей, как bashread builtin сделает рудиментарное разделение поля для вас, если вы дадите ему несколько переменных. Кроме того, вы все равно не используете name, поэтому он не нужен. cat не нужен.

В зависимости от вашего точного варианта использования даже grep может быть ненужным, делая внутреннюю команду просто sed -ne "s/${goterm}/pi/gp" GOEA.csv. Если ваша цель для grep -w не исключают строки, где ${goterm} подстрока слова вместо целого слова ...

Для дальнейшего использования, вставив set -x выше ваш цикл в вашем сценарии покажут вам точные команды, чтобы вы могли сравнить их с вашими ожиданиями.

1

Давайте очистить этот код немного:

while read goterm name 
do 
    grep -w "$goterm" GOEA.csv | sed "s/$goterm/pi/g" 
done < BP.cvs 

Проблема заключается в том, что ваши заявления AWK пытаются читать из STDIN так же, как ваш while делает. Вы читаете из одного входного потока.

Что вы хотите сделать, это вытащить значения из вашей линии. Для этого я использую read. Оператор read использует значения в $IFS для выделения ввода. Обычно это пробелы, вкладки и новые строки. read считывает каждую переменную, помещенную в строку, и последнее значение, которое читается, содержит всю оставшуюся часть строки.

Таким образом:

while read line 

читает всей линии в то время как:

while goterm name 

сломается линию, как

goterm="GO:0008283" 
name="cell proliferation" 

еще одна вещь.При использовании grep и sed вместе, вы, вероятно, может уйти только с sed:

while read goterm name 
do 
    sed -n "/$goterm/s/$goterm/pi/gp" GOEA.csv 
done < BP.csv 

Формат для SED команды:

/lines/command/parameters/ 

Итак, я ищу для линий с $goterm в их, затем я заменяю $goterm на pi. Значения -n не распечатывают линии, так как sed обрабатывает их, а p означает распечатать строки, в которых находится замена.

К слову, csv в качестве файлового суффикса означает значения, разделенные запятой, но ни один файл не похож, что он разделен запятой. Эти вкладки разделяют каждое поле. Если это так, вам нужно изменить $IFS на вкладки.

Смежные вопросы