如何从sh中的文件中获取价值?

时间:2018-11-22 18:37:15

标签: bash unix sh

设置:

文件a包含:

22

文件b包含:

12

我有shell 脚本 1.sh

#!/bin/sh

a=$(< a)
b=$(< b)
echo $(($a*$b)) > c

该脚本应该从文件ab获取值,将其乘以*,然后保存到文件c。 但是,设置权限$ chmod a+rx 1.sh并运行$ ./1.sh后,它会返回错误

./1.sh: 5: ./1.sh: arithmetic expression: expecting primary: "*"

发生此错误是因为变量$a$b没有获得值形式文件ab

  • 如果我echo $aecho $b不返回任何内容;
  • 如果我在脚本中定义了a=22b=12值,那么它将起作用;
  • 我还尝试了其他方法来获取文件内容,例如a=$(< 'a')a=$(< "a")a=$(< "~/a")甚至a=$(< cat a)。这些都不起作用。

剧情扭曲:

但是,如果我将shebang行更改为#!/bin/bash,以便使用 Bash shell -它可以工作。

问题:

如何从 sh 中的文件中正确获取数据?

3 个答案:

答案 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的行结尾,则可能需要对其进行修改。


附录:

Process Substitution

  

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下尝试了您的原始示例,并且假设ab具有UNIX行尾,它的运行正常。如果不能保证,并且您需要在#!/bin/sh下运行(由bash模拟),则可以使用以下方法:

#!/bin/sh
a=$(<a)
b=$(<b)
echo $(( ${a%%[^0-9]*} * ${b%%[^0-9]*} )) > c