我有这种代码的和平:
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
更改为字符串“pi”,但它会给出:
sed: -e expression #1, char 12: unterminated `s' command
为什么呢? 感谢。
答案 0 :(得分: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)
让我们稍微清理一下这段代码:
while read goterm name
do
grep -w "$goterm" GOEA.csv | sed "s/$goterm/pi/g"
done < BP.cvs
问题是你的awk语句试图像你while
那样从STDIN读入。您正在读取相同的输入流。
您要做的是从您的行中提取值。我正在使用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
作为标签。
答案 2 :(得分:0)
我会重整整个事情:
while read goterm restofline
do
grep -w "${goterm}" GOEA.csv | sed -e "s/${goterm}/pi/g"
done < BP.csv
没有理由awk
内容,因为bash
read
内置将为您提供基本字段拆分,如果您给它多个变量。此外,您无论如何都不使用name
,因此不需要它。 cat
也是不必要的。
根据您的确切用例,即使是grep
也可能是不必要的,因此内部命令只需sed -ne "s/${goterm}/pi/gp" GOEA.csv
。除非你grep -w
的目的是消除${goterm}
是一个单词的子串而不是整个单词的行......
为了将来参考,在您的脚本中在循环上方插入set -x
会向您显示正在运行的命令,以便您可以将它们与您的期望进行比较。