我有一个文件,其中包含我正在检索的信息
命令
cat 2018_02_15_09_01_08_result.tsv | grep -o [A-Z]\\*[0-9]*:[0-9]* | sort | uniq | sed -e 's/^/HLA-/' |tr '\n' ',' | sed '$ s/.$//'
产量
HLA-A*30:02,HLA-B*18:01,HLA-C*05:01
但我试图将其保存在变量中,星号和字母消失,我尝试了几种方法,添加/删除逗号等,但我还是无法正确打印它。
hla=`cat 2018_02_15_09_01_08_result.tsv | grep -o [A-Z]\\*[0-9]*:[0-9]* | sort | uniq | sed -e 's/^/HLA-/' |tr '\n' ',' | sed '$ s/.$//'`
echo $hla
HLA-05:01,HLA-18:01,HLA-30:02
echo "$hla"
HLA-05:01,HLA-18:01,HLA-30:02
这里存在多个错误,其中大多数错误将由http://shellcheck.net/恰当地诊断,无需任何人为干预。
`command`
在反引号内的字符串上引入了一些不幸的额外shell处理。自20世纪90年代以来的解决方案是更喜欢使用$(command)
语法进行命令替换,但这并没有出现这个问题。cat
is useless; grep
非常了解如何阅读文件。试试这个重构的代码:
hla=$(grep -o '[A-Z]*[0-9]*:[0-9]*' 2018_02_15_09_01_08_result.tsv |
sort -u | sed -e 's/^/HLA-/' |tr '\n' ',' | sed '$ s/.$//')
echo "$hla"
echo
中变量插值周围的双引号是necessary and useful;另请注意,线条包含易读性和使用sort -u
优先于sort | uniq
(并且通常会尝试减少进程的数量 - 一旦我理解了sed | tr | sed
的作用,我也可以提出简化)。也许最简单的解决方法是将所有这些重构为单个Awk脚本,但如果无法访问输入,则很难更详细地告诉您这可能是什么样子。
(另外,你真的确定你需要将值捕获到一个变量吗?通常variable=value; echo "$variable"
只是一种模糊和低效的方式来说echo "value"
。而variable=$(command); echo "$variable"
更好地编写简单的command
并捕获命令的标准输出只是为了你可以将它打印到标准输出是纯粹的循环浪费,除非你打算用这个变量的值做更多的事情。)
我通过重定向保存命令的输出来解决它:
cat 2018_02_15_09_01_08_result.tsv |
grep -o [A-Z]\\*[0-9]*:[0-9]* |
sort | uniq |
sed -e 's/^/HLA-/' |tr '\n' ',' | sed '$ s/.$//' > out_file
hla=`cat out_file`
echo $hla
这让我得到了预期的HLA-A*30:02,HLA-B*18:01,HLA-C*05:01
。不是理想的解决方案,但它确实有效。