文件a
包含:
22
文件b
包含:
12
我有shell 脚本 1.sh
:
#!/bin/sh
a=$(< a)
b=$(< b)
echo $(($a*$b)) > c
该脚本应该从文件a
和b
获取值,将其乘以*
,然后保存到文件c
。
但是,设置权限$ chmod a+rx 1.sh
并运行$ ./1.sh
后,它会返回错误:
./1.sh: 5: ./1.sh: arithmetic expression: expecting primary: "*"
发生此错误是因为变量$a
和$b
没有获得值形式文件a
和b
。
echo $a
和echo $b
不返回任何内容; a=22
和b=12
值,那么它将起作用; a=$(< 'a')
,a=$(< "a")
,a=$(< "~/a")
甚至a=$(< cat a)
。这些都不起作用。但是,如果我将shebang行更改为#!/bin/bash
,以便使用 Bash shell -它可以工作。
如何从 sh 中的文件中正确获取数据?
答案 0 :(得分:1)
忽略文件a和b中的所有内容,但忽略数字:
#!/bin/sh
a=$(tr -cd 0-9 < a)
b=$(tr -cd 0-9 < b)
echo $(($a*$b))
请参阅:man tr
答案 1 :(得分:0)
有很多方法。一种明显的方法是通过命令替换
在子流程中进行管道传输:A=$(cat fileA.txt) # 22
B=$(cat fileB.txt) # 12
echo $((A*B))
# <do it in your head!>
如果多行还有其他问题,则需要研究如何使用Bash变量$IFS
(内部文件分隔符)。通常IFS
的定义是:IFS=$' \t\n'
,因此,如果您需要能够可靠地读取Windows和Linux EOL的行结尾,则可能需要对其进行修改。
附录:
Bash,Zsh 和AT&T ksh {88,93}(但不是 pdksh / mksh )支持过程 代换。 POSIX未指定进程替换。你可以 使用NamedPipes完成相同的操作。协同过程也可以 所有过程替代都可以,并且移植性更高 (尽管使用它们的语法不是)。
这也意味着大多数Android OS不允许进程替换,因为它们的外壳通常基于 mksh 。
来自 man bash
:
Process Substitution
Process substitution allows a process's input or output to be referred to using a filename. It takes the form of <(list) or >(list). The
process list is run asynchronously, and its input or output appears as a filename. This filename is passed as an argument to the current
command as the result of the expansion. If the >(list) form is used, writing to the file will provide input for list. If the <(list) form
is used, the file passed as an argument should be read to obtain the output of list. Process substitution is supported on systems that sup-
port named pipes (FIFOs) or the /dev/fd method of naming open files.
When available, process substitution is performed simultaneously with parameter and variable expansion, command substitution, and arithmetic
expansion.
答案 2 :(得分:0)
如果您要寻找“真正的” Bourne-Shell兼容性,而不是Bash的仿真,那么您就必须走老路:
#!/bin/sh
a=`cat a`
b=`cat b`
expr $a \* $b > c
我在macOS和Linux(FC26)上的#!/bin/sh
下尝试了您的原始示例,并且假设a
和b
具有UNIX行尾,它的运行正常。如果不能保证,并且您需要在#!/bin/sh
下运行(由bash
模拟),则可以使用以下方法:
#!/bin/sh
a=$(<a)
b=$(<b)
echo $(( ${a%%[^0-9]*} * ${b%%[^0-9]*} )) > c