Bash 使用awk命令比较单独行上的值?
我正在尝试构建一个bash脚本,该脚本使用awk命令逐行遍历一个以制表符分隔的排序文件,并确定是否:Bash 使用awk命令比较单独行上的值?,bash,for-loop,awk,Bash,For Loop,Awk,我正在尝试构建一个bash脚本,该脚本使用awk命令逐行遍历一个以制表符分隔的排序文件,并确定是否: 该行的字段1(分子)与下一行相同 行的字段5(绞线)是字符串“减号”,并且 下一行的字段5是字符串“plus” 如果这是真的,我想将第1行的字段1和3中的值以及下一行的字段4中的值添加到文件中。对于上下文,排序后,输入文件如下所示: molecule gene start end strand ERR2661861.3269 JN051170.1 113
molecule gene start end strand
ERR2661861.3269 JN051170.1 11330 10778 minus
ERR2661861.3269 JN051170.1 11904 11348 minus
ERR2661861.3269 JN051170.1 12418 11916 minus
ERR2661861.3269 JN051170.1 13000 12469 minus
ERR2661861.3269 JN051170.1 13382 13932 plus
ERR2661861.3269 JN051170.1 13977 14480 plus
ERR2661861.3269 JN051170.1 14491 15054 plus
ERR2661861.3269 JN051170.1 15068 15624 plus
ERR2661861.3269 JN051170.1 15635 16181 plus
因此,在本例中,在比较第4行和第5行时,脚本应该找到true语句,并将以下行附加到文件中:
ERR2661861.3269 13000 13382
到目前为止,我的剧本是:
# test input file
file=Eg2.1.txt.out
#sort the file by 'molecule' field, then 'start' field
sort -k1,1 -k3n $file > sorted_file
# create output file and add 'molecule' 'start' and 'end' headers
echo molecule$'\t'start$'\t'end >> Test_file.txt
# for each line of the input file, do this
for i in $sorted_file
do
# check to see if field 1 on current line is the same as field 1 on next line AND if field 5 on current line is "minus" AND if field 5 on next line is "plus"
if [awk '{if(NR==i) print $1}' == awk '{if(NR==i+1) print $1}'] && [awk '{if(NR==i) print $5}' == "minus"] && [awk '{if(NR==i+1) print $5}' == "plus"];
# if this is true, then get the 1st and 3rd fields from current line and 4th field from next line and add this to the output file
then
mol=awk '{if(NR==i) print $1}'
start=awk '{if(NR==i) print $3}'
end=awk '{if(NR==i+1) print $4}'
new_line=$mol$'\t'$start$'\t'$end
echo new_line >> Test_file.txt
fi
done
bash脚本的第一部分按照我的要求工作,但是for循环似乎在排序文件中找不到任何点击。是否有人有任何见解或建议来解释为什么这可能无法达到预期效果
非常感谢 解释为什么您的代码不工作
有关问题的更好解决方案,请参阅
bash中的字符串比较需要[
和]
Bash解释您的命令
[awk '{if(NR==i) print $1}' == awk '{if(NR==i+1) print $1}']
。。。由于命令[awk
带有参数{if(NR..
,=
,awk
和{if(NR..]
。在您的平均系统中,没有名为[awk
的命令,因此这应该会失败并显示一条错误消息。在[
和]之前添加一个空格
awk
未执行
[awk=awk]
只比较文字字符串awk
。要执行命令并比较其输出,请使用[“$(awk)”=“$(awk)”]
awk
缺少输入文件
awk'{…}'
尝试从stdin(在您的情况下是用户)读取输入。由于要读取该文件,请将其添加为参数:awk'{…}'排序的\u文件
awk'..NR==i…“
没有引用bash的中的i
awk
不知道您的bash变量。当您在awk
脚本中写入i
时,i
将始终具有默认值0
。要将变量从bash
传递到awk
请使用awk-v i=“$i”…
。此外,您似乎假设for i in
将迭代文件的行号。现在,情况并非如此,请参见下一段
$sorted_file中的i的未迭代文件sorted_file
您调用了您的文件sorted\u file
。但是当您编写$sorted\u file
时,您引用了一个以前未声明的变量。未声明的变量扩展为空字符串,因此您不会迭代任何内容。
您可能想为$(cat sorted_file)中的i编写,
,但这将迭代文件内容,而不是行号。此外,根据文件内容,未加引号的$()
可能会导致无法格式化的问题。要迭代行号,请使用for i in$(seq$(wc-l sorted_file))
解释您的代码不起作用的原因
有关问题的更好解决方案,请参阅
bash中的字符串比较需要[
和]
Bash解释您的命令
[awk '{if(NR==i) print $1}' == awk '{if(NR==i+1) print $1}']
…作为参数为{if(NR.
,=
,awk
和{if(NR.]
的命令[awk
。在您的平均系统中,没有名为[awk
的命令,因此这应该会失败并显示一条错误消息。在[
之后和之前添加一个空格
awk
未执行
[awk=awk]
只比较文字字符串awk
。要执行命令并比较其输出,请使用[“$(awk)”=“$(awk)”]
awk
缺少输入文件
awk'{…}'
尝试从stdin(在您的情况下是用户)读取输入。由于要读取该文件,请将其添加为参数:awk'{…}'排序的\u文件
awk'..NR==i…“
没有引用bash的中的i
awk
不知道您的bash变量。当您在awk
脚本中写入i
时,i
将始终具有默认值0
。要将变量从bash
传递到awk
请使用awk-v i=“$i”…
。此外,您似乎假设for i in
将迭代文件的行号。现在,情况并非如此,请参见下一段
$sorted_file中的i的未迭代文件sorted_file
您调用了您的文件sorted\u file
。但是当您编写$sorted\u file
时,您引用了一个以前未声明的变量。未声明的变量扩展为空字符串,因此您不会迭代任何内容。
您可能想为$(cat sorted_file)中的i编写,
,但这将迭代文件内容,而不是行号。此外,根据文件内容,未加引号的$()
可能会导致无法格式化的问题。要迭代行号,请使用for i in$(seq$(wc-l sorted_file))
这将完成最后一步,假设数据在键中排序,“减”在“加”之前
请注意,awk
有一个隐式循环,无需强制它在外部进行迭代。这将完成最后一步,假设数据在键中排序,“减”在“加”之前
请注意,awk
有一个隐式循环,无需强制它在外部进行迭代。当使用awk或任何其他程序比较流中的相邻行时,最好的做法是存储该行的相关数据,然后在两行都被读取后立即进行比较,如
molecule = $1
strand = $5
if (molecule==last_molecule)
if (last_strand=="minus")
if (strand=="plus")
print $1,end,$4
last_molecule = molecule
last_strand = strand
end = $3
perl -lanE 'if ($l0==$F[0] && $l4 eq "minus" && $F[4] eq "plus") {say join("\t", @F[0..2])}
$l0=$F[0]; $l4=$F[4];' sorted_file
awk '($1==l1 && l5=="minus" && $5=="plus"){print $1 "\t" $2 "\t" $3}
{l1=$1;l5=$5}' sorted_file
ruby -lane 'BEGIN{l0=l4=""}
puts $F[0..2].join("\t") if (l0==$F[0] && l4=="minus" && $F[4]=="plus")
l0=$F[0]; l4=$F[4]
' sorted_file
ERR2661861.3269 JN051170.1 13382