如何在bash中使用csv文件作为基本算术运算的输入

如何在bash中使用csv文件作为基本算术运算的输入,bash,csv,math,Bash,Csv,Math,我将数据存储在neckrev_dim.csv文件中,结构如下 subjectID,dim3,pixdim3 MR44825,405,0.625 我还有一个单独的subjects.csv,只包含所有的subjects MR44825 MR55843 现在我想使用bash在基本算术运算中使用这些数据 subjlist=subjects.csv for subj in ` cat $subjlist ` do dim3=$(grep -w '$subj' neckrev_dim.csv

我将数据存储在neckrev_dim.csv文件中,结构如下

subjectID,dim3,pixdim3 
MR44825,405,0.625
我还有一个单独的subjects.csv,只包含所有的subjects

MR44825
MR55843
现在我想使用bash在基本算术运算中使用这些数据

subjlist=subjects.csv
for subj in ` cat $subjlist `
do
    dim3=$(grep -w '$subj' neckrev_dim.csv | cut -d ',' -f 2)
    pixdim3=$(grep -w '$subj' neckrev_dim.csv | cut -d ',' -f 3)
    total_length=$(($dim3*$pixdim3))
    echo $total_length
done
这会导致以下错误:

syntax error: operand expected (error token is "*")
我认为问题在于grep,但我无法解决


提前谢谢

您需要将$sub周围的单引号更改为双引号。单引号不会扩展变量。

您需要将$sub周围的单引号更改为双引号。单引号不能扩展变量。

主要问题是POSIX算法不支持小数,只支持整数

您必须使用其他方法,例如非整数算术

另一个问题是,您使用的是单引号$subh-您应该使用双引号,以便变量得到扩展

请尝试以下操作:

subjlist=subjects.csv

while read -r subj
do
    dim3=$(grep -w "$subj" neckrev_dim.csv | cut -d ',' -f 2)
    pixdim3=$(grep -w "$subj" neckrev_dim.csv | cut -d ',' -f 3)
    echo "$dim3 * $pixdim3" | bc
done < "$subjlist"

注意,这里bc是从标准输入读取的,所以我们只需要将算术表达式回送到bc。

主要问题是POSIX算术不支持小数,只支持整数

您必须使用其他方法,例如非整数算术

另一个问题是,您使用的是单引号$subh-您应该使用双引号,以便变量得到扩展

请尝试以下操作:

subjlist=subjects.csv

while read -r subj
do
    dim3=$(grep -w "$subj" neckrev_dim.csv | cut -d ',' -f 2)
    pixdim3=$(grep -w "$subj" neckrev_dim.csv | cut -d ',' -f 3)
    echo "$dim3 * $pixdim3" | bc
done < "$subjlist"

注意,这里bc是从标准输入读取的,因此我们只需要将算术表达式回送到bc。

下面的解决方案旨在更准确、更普遍地适用于不同类型的键值和不同的CSV行,从而避免其他解决方案的一些限制和故障模式

代码说明 使用从文件keys.txt中每行读取一个单键字段,在CSV文件generic.CSV的第一个字段中搜索该键,并对其他字段中的数字进行浮点非整数运算

性能增强: 如果$key选择了文件中唯一的一行,则将下面的XexitX更改为exit,这样awk就不会不必要地继续读取文件的其余部分;否则,删除XexitX,它将执行与该键匹配的所有行。 如果generic.csv是一个大文件,则对其进行排序,并用look-binary行替换awk行。这将用二进制搜索代替线性搜索。确保对整个文件进行排序: 排序-o generic.csv generic.csv 限制: $key在awk版本中不得包含反斜杠或双引号。这可以通过在字段上使用sed-e的/\\/&&/g'-e的/\\\/g'来修复。look-binary版本不在乎。 generic.csv文件必须仅使用逗号,不使用带引号的csv字段。这意味着任何字段都不能包含逗号。 look-binary版本在CSV行上进行键前缀匹配,因此不能有一个键是另一个的前缀,例如,键ABC和AB不区分。awk版本没有这个问题。 与其他解决方案相比,此解决方案的优势: 每个密钥只读取CSV一次,而不是多次。 $key在第一个字段上完全匹配,而不是在可能添加到CSV行其余部分的任何字段上-没有错误匹配。look-binary版本进行前缀匹配,因此不能有一个键是另一个的前缀。 键字段是文本字段,而不是正则表达式,因此它可能包含特殊字符,而无需担心转义正则表达式元字符以避免错误。 不需要使用grep或cut来分隔字段;只有一根管子,不是三根。 通过使用look-binary而不是awk,可以轻松地扩展到巨大的CSV文件。
下面的解决方案旨在更准确地适用于不同类型的键值和不同的CSV行,避免了其他解决方案的一些限制和故障模式

代码说明 使用从文件keys.txt中每行读取一个单键字段,在CSV文件generic.CSV的第一个字段中搜索该键,并对其他字段中的数字进行浮点非整数运算

性能增强: 如果$key选择了文件中唯一的一行,则将下面的XexitX更改为exit,这样awk就不会不必要地继续读取文件的其余部分;否则,删除XexitX,它将执行与该键匹配的所有行。 如果generic.csv是一个大文件,则对其进行排序,并用look-binary行替换awk行。这将用二进制搜索代替线性搜索。确保对整个文件进行排序: 排序-o generic.csv generic.csv 限制: $key在awk版本中不得包含反斜杠或双引号。这可以通过在字段上使用sed-e的/\\/&&/g'-e的/\\\/g'来修复。look-binary版本不在乎。 generic.csv文件必须仅使用逗号,不使用带引号的csv字段。这意味着任何字段都不能包含逗号。 look-binary版本在CSV行上进行键前缀匹配,因此不能有一个键是另一个的前缀,例如,键ABC和AB不是d 独特的。awk版本没有这个问题。 与其他解决方案相比,此解决方案的优势: 每个密钥只读取CSV一次,而不是多次。 $key在第一个字段上完全匹配,而不是在可能添加到CSV行其余部分的任何字段上-没有错误匹配。look-binary版本进行前缀匹配,因此不能有一个键是另一个的前缀。 键字段是文本字段,而不是正则表达式,因此它可能包含特殊字符,而无需担心转义正则表达式元字符以避免错误。 不需要使用grep或cut来分隔字段;只有一根管子,不是三根。 通过使用look-binary而不是awk,可以轻松地扩展到巨大的CSV文件。
啊,太好了,非常感谢!这已经解决了我的第一个问题。现在唯一的问题是,我使用将pixdim3存储为十进制,所以它向我抛出了另一个错误497*0.400024:语法错误:无效算术运算符错误标记为.400024。你知道一个简单的解决方法吗?Bash不能处理浮点。。。试试total=$dc-e$dim3$pixdim3*p。太好了,它就像一个符咒!谢谢你的时间。啊,太好了,非常感谢!这已经解决了我的第一个问题。现在唯一的问题是,我使用将pixdim3存储为十进制,所以它向我抛出了另一个错误497*0.400024:语法错误:无效算术运算符错误标记为.400024。你知道一个简单的解决方法吗?Bash不能处理浮点。。。试试total=$dc-e$dim3$pixdim3*p。太好了,它就像一个符咒!谢谢你的时间。效果也很好!谢谢你的解决方案和对我犯错误的解释。效果也很好!谢谢你的解答和对我犯错误的解释。