如何在 Bash 脚本中添加数字?

发布于 2024-11-15 05:04:02 字数 358 浏览 2 评论 0原文

我有这个 Bash 脚本,但在第 16 行遇到了问题。 我如何获取第 15 行的先前结果并添加 它到第 16 行的变量?

#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do
    for j in `ls output-$i-*`; do
        echo "$j"

        metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
        num= $num + $metab   (line16)
    done
    echo "$num"
 done

I have this Bash script and I had a problem in line 16.
How can I take the previous result of line 15 and add
it to the variable in line 16?

#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do
    for j in `ls output-$i-*`; do
        echo "$j"

        metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
        num= $num + $metab   (line16)
    done
    echo "$num"
 done

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(15

橘和柠 2024-11-22 05:04:02

对于整数

  • 使用算术扩展$((EXPR))

    num=$((num1 + num2))
    num=$(($num1 + $num2)) # 也有效
    num=$((num1 + 2 + 3)) # ...
    num=$[num1+num2] # 旧的、已弃用的算术表达式语法
    
  • 使用外部 expr 实用程序。请注意,这仅适用于非常旧的系统。

    num=`expr $num1 + $num2` # expr 的空格很重要
    

对于浮点

Bash 不直接支持这一点,但是您可以使用一些外部工具:

num=$(awk "BEGIN {print $num1+$num2; exit}")
num=$(python -c "print $num1+$num2")
num=$(perl -e "print $num1+$num2")
num=$(echo $num1 + $num2 | bc)   # Whitespace for echo is important

您还可以使用科学计数法(例如,2.5e+2)。


常见陷阱

  • 设置变量时,= 两边不能有空格,否则会强制 shell 将第一个单词解释为变量的名称要运行的应用程序(例如,num=num

    num= 1 num =2

  • bcexpr 期望每个数字和运算符作为单独的参数,因此空格很重要。它们无法处理像 3+ +4 这样的参数。

    num=`expr $num1+ $num2`

For integers:

  • Use arithmetic expansion: $((EXPR))

    num=$((num1 + num2))
    num=$(($num1 + $num2))       # Also works
    num=$((num1 + 2 + 3))        # ...
    num=$[num1+num2]             # Old, deprecated arithmetic expression syntax
    
  • Using the external expr utility. Note that this is only needed for really old systems.

    num=`expr $num1 + $num2`     # Whitespace for expr is important
    

For floating point:

Bash doesn't directly support this, but there are a couple of external tools you can use:

num=$(awk "BEGIN {print $num1+$num2; exit}")
num=$(python -c "print $num1+$num2")
num=$(perl -e "print $num1+$num2")
num=$(echo $num1 + $num2 | bc)   # Whitespace for echo is important

You can also use scientific notation (for example, 2.5e+2).


Common pitfalls:

  • When setting a variable, you cannot have whitespace on either side of =, otherwise it will force the shell to interpret the first word as the name of the application to run (for example, num= or num)

    num= 1 num =2

  • bc and expr expect each number and operator as a separate argument, so whitespace is important. They cannot process arguments like 3+ +4.

    num=`expr $num1+ $num2`

鲸落 2024-11-22 05:04:02

使用$(( ))算术展开式。

num=$(( $num + $metab ))

有关详细信息,请参阅第 13 章算术扩展

Use the $(( )) arithmetic expansion.

num=$(( $num + $metab ))

See Chapter 13. Arithmetic Expansion for more information.

云归处 2024-11-22 05:04:02

有一千零一种方法可以做到这一点。这是使用 dc (一种逆波兰式桌面计算器,支持无限精度算术):

dc <<<"$num1 $num2 + p"

但如果这对你来说太笨拙了(或者可移植性很重要),你可以说

echo $num1 $num2 + p | dc

但也许你是那些认为 RPN 令人讨厌和奇怪的人之一;不用担心! bc 就在这里为您服务:

bc <<< "$num1 + $num2"
echo $num1 + $num2 | bc

也就是说,有一些您可以对脚本进行不相关的改进:

#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do
    for j in output-$i-* ; do # 'for' can glob directly, no need to ls
            echo "$j"

             # 'grep' can read files, no need to use 'cat'
            metab=$(grep EndBuffer "$j" | awk '{sum+=$2} END { print sum/120}')
            num=$(( $num + $metab ))
    done
    echo "$num"
done

Bash FAQ 022 中所述,Bash 本身并不支持浮点数。如果您需要对浮点数求和,则需要使用外部工具(例如 bcdc)。

在这种情况下,解决方案是将

num=$(dc <<<"$num $metab + p")

累积可能的浮点数添加到num中。

There are a thousand and one ways to do it. Here's one using dc (a reverse Polish desk calculator which supports unlimited precision arithmetic):

dc <<<"$num1 $num2 + p"

But if that's too bash-y for you (or portability matters) you could say

echo $num1 $num2 + p | dc

But maybe you're one of those people who thinks RPN is icky and weird; don't worry! bc is here for you:

bc <<< "$num1 + $num2"
echo $num1 + $num2 | bc

That said, there are some unrelated improvements you could be making to your script:

#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do
    for j in output-$i-* ; do # 'for' can glob directly, no need to ls
            echo "$j"

             # 'grep' can read files, no need to use 'cat'
            metab=$(grep EndBuffer "$j" | awk '{sum+=$2} END { print sum/120}')
            num=$(( $num + $metab ))
    done
    echo "$num"
done

As described in Bash FAQ 022, Bash does not natively support floating point numbers. If you need to sum floating point numbers the use of an external tool (like bc or dc) is required.

In this case the solution would be

num=$(dc <<<"$num $metab + p")

To add accumulate possibly-floating-point numbers into num.

前事休说 2024-11-22 05:04:02

在 Bash 中,

num=5
x=6
(( num += x ))
echo $num   # ==> 11

请注意,Bash 只能处理整数算术,因此,如果您的 AWK 命令返回分数,那么您需要重新设计:这里是您的代码,稍微重写了一下,以便在 AWK 中完成所有数学运算。

num=0
for ((i=1; i<=2; i++)); do
    for j in output-$i-*; do
        echo "$j"
        num=$(
           awk -v n="$num" '
               /EndBuffer/ {sum += $2}
               END {print n + (sum/120)}
           ' "$j"
        )
    done
    echo "$num"
done

In Bash,

num=5
x=6
(( num += x ))
echo $num   # ==> 11

Note that Bash can only handle integer arithmetic, so if your AWK command returns a fraction, then you'll want to redesign: here's your code rewritten a bit to do all math in AWK.

num=0
for ((i=1; i<=2; i++)); do
    for j in output-$i-*; do
        echo "$j"
        num=$(
           awk -v n="$num" '
               /EndBuffer/ {sum += $2}
               END {print n + (sum/120)}
           ' "$j"
        )
    done
    echo "$num"
done
七颜 2024-11-22 05:04:02

我总是忘记语法,所以我来到 Google 搜索,但我再也找不到我熟悉的语法了:P。这对我来说是最干净的,也更符合我对其他语言的期望。

i=0
((i++))

echo $i;

I always forget the syntax so I come to Google Search, but then I never find the one I'm familiar with :P. This is the cleanest to me and more true to what I'd expect in other languages.

i=0
((i++))

echo $i;
茶色山野 2024-11-22 05:04:02

我也非常喜欢这个方法。混乱更少:

count=$[count+1]

I really like this method as well. There is less clutter:

count=$[count+1]
瘫痪情歌 2024-11-22 05:04:02
#!/bin/bash
read X
read Y
echo "$(($X+$Y))"
#!/bin/bash
read X
read Y
echo "$(($X+$Y))"
一片旧的回忆 2024-11-22 05:04:02

您应该将 metab 声明为整数,然后使用算术求值

declare -i metab num
...
num+=metab
...

有关详细信息,请参阅6.5 Shell 算术

You should declare metab as integer and then use arithmetic evaluation

declare -i metab num
...
num+=metab
...

For more information, see 6.5 Shell Arithmetic.

千纸鹤带着心事 2024-11-22 05:04:02

使用 shell 内置 let。它类似于 (( expr ))

A=1
B=1
let "C = $A + $B"
echo $C # C == 2

来源:Bash let 内置命令

Use the shell built-in let. It is similar to (( expr )):

A=1
B=1
let "C = $A + $B"
echo $C # C == 2

Source: Bash let builtin command

最美的太阳 2024-11-22 05:04:02

另一种在 Bash 中执行的可移植的 POSIX 兼容方式,可以在 .bashrc 为所有方便的算术运算符。

addNumbers () {
    local IFS='+'
    printf "%s\n" "$(( $* ))"
}

只需在命令行中调用它即可,

addNumbers 1 2 3 4 5 100
115

其想法是使用 Input-Field-Separator(IFS ),Bash 中的一个特殊变量,用于扩展后的单词拆分以及将行拆分为单词。该函数在本地更改值以使用分词字符作为求和运算符 +

请记住,IFS 是在本地更改的,并且不会对函数作用域外的默认 IFS 行为生效。摘自 man bash 页面,

shell 将 IFS 的每个字符视为分隔符,并将其他扩展的结果拆分为这些字符上的单词。如果 IFS 未设置,或者其值恰好是默认值,则忽略先前扩展结果的开头和结尾处的 、 、 和 序列,并且不在开头或结尾处的任何 IFS 字符序列用于分隔话。

"$(( $* ))" 表示传递的参数列表,由 + 分割,然后使用 printf 输出总和值代码>函数。该函数还可以扩展以增加其他算术运算的范围。

Another portable POSIX compliant way to do in Bash, which can be defined as a function in .bashrc for all the arithmetic operators of convenience.

addNumbers () {
    local IFS='+'
    printf "%s\n" "$(( $* ))"
}

and just call it in command-line as,

addNumbers 1 2 3 4 5 100
115

The idea is to use the Input-Field-Separator(IFS), a special variable in Bash used for word splitting after expansion and to split lines into words. The function changes the value locally to use word-splitting character as the sum operator +.

Remember the IFS is changed locally and does not take effect on the default IFS behaviour outside the function scope. An excerpt from the man bash page,

The shell treats each character of IFS as a delimiter, and splits the results of the other expansions into words on these characters. If IFS is unset, or its value is exactly , the default, then sequences of , , and at the beginning and end of the results of the previous expansions are ignored, and any sequence of IFS characters not at the beginning or end serves to delimit words.

The "$(( $* ))" represents the list of arguments passed to be split by + and later the sum value is output using the printf function. The function can be extended to add scope for other arithmetic operations also.

暮倦 2024-11-22 05:04:02
#!/usr/bin/bash

#integer numbers
#===============#

num1=30
num2=5

echo $(( num1 + num2 ))
echo $(( num1-num2 ))
echo $(( num1*num2 ))
echo $(( num1/num2 ))
echo $(( num1%num2 ))

read -p "Enter first number : " a
read -p "Enter second number : " b
# we can store the result
result=$(( a+b ))
echo sum of $a \& $b is $result # \ is used to espace &


#decimal numbers
#bash only support integers so we have to delegate to a tool such as bc
#==============#

num2=3.4
num1=534.3

echo $num1+$num2 | bc
echo $num1-$num2 | bc
echo $num1*$num2 |bc
echo "scale=20;$num1/$num2" | bc
echo $num1%$num2 | bc

# we can store the result
#result=$( ( echo $num1+$num2 ) | bc )
result=$( echo $num1+$num2 | bc )
echo result is $result

##Bonus##
#Calling built in methods of bc 

num=27

echo "scale=2;sqrt($num)" | bc -l # bc provides support for calculating square root

echo "scale=2;$num^3" | bc -l # calculate power
#!/usr/bin/bash

#integer numbers
#===============#

num1=30
num2=5

echo $(( num1 + num2 ))
echo $(( num1-num2 ))
echo $(( num1*num2 ))
echo $(( num1/num2 ))
echo $(( num1%num2 ))

read -p "Enter first number : " a
read -p "Enter second number : " b
# we can store the result
result=$(( a+b ))
echo sum of $a \& $b is $result # \ is used to espace &


#decimal numbers
#bash only support integers so we have to delegate to a tool such as bc
#==============#

num2=3.4
num1=534.3

echo $num1+$num2 | bc
echo $num1-$num2 | bc
echo $num1*$num2 |bc
echo "scale=20;$num1/$num2" | bc
echo $num1%$num2 | bc

# we can store the result
#result=$( ( echo $num1+$num2 ) | bc )
result=$( echo $num1+$num2 | bc )
echo result is $result

##Bonus##
#Calling built in methods of bc 

num=27

echo "scale=2;sqrt($num)" | bc -l # bc provides support for calculating square root

echo "scale=2;$num^3" | bc -l # calculate power
情徒 2024-11-22 05:04:02
#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do      
    for j in `ls output-$i-*`; do
        echo "$j"

        metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
        let num=num+metab (line 16)
    done
    echo "$num"
done
#!/bin/bash

num=0
metab=0

for ((i=1; i<=2; i++)); do      
    for j in `ls output-$i-*`; do
        echo "$j"

        metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
        let num=num+metab (line 16)
    done
    echo "$num"
done
北音执念 2024-11-22 05:04:02

适用于 MacOS。 bc 是一个命令行计算器

#!/bin/bash

sum=0
for (( i=1; i<=5; i++ )); do
    sum=$(echo "$sum + 1.1" | bc) # bc: if you want to use decimal
done
echo "Total: $sum"

Works on MacOS. bc is a command line calculator

#!/bin/bash

sum=0
for (( i=1; i<=5; i++ )); do
    sum=$(echo "$sum + 1.1" | bc) # bc: if you want to use decimal
done
echo "Total: $sum"
独木成林 2024-11-22 05:04:02

这是我的解决方案

5.1

git clone https://github.com/datablist/sample-csv-files.git

5.2

cd sample-csv-files
git log --pretty=format:"%h - %s" -n 3

5.3

awk -F, 'NR>=40 && NR<=70 {print $1":"$2":"$3}' files/people/people-100.csv

5.4

#!/bin/bash

if [ "$#" -ne 1 ]; then
echo "Utilizare: $0 adresa_de_email"
exit 1
fi

EMAIL=$1

FILE="files/people/people-10000.csv"

RESULT=$(grep -n "$EMAIL" "$FILE")

if [ -z "$RESULT" ]; then
echo "Adresa de email '$EMAIL' nu a fost găsită."
else
echo "Date găsite: $RESULT"
fi

1

这是我的解决方案:

5.1

mkdir -p ~/student/my-app
cd ~/student/my-app
git init

5.2

echo "Hello, World!" > ~/student/my-app/hello.txt
cd ~/student/my-app
git add hello.txt
git commit -m "Added hello.txt with 'Hello, World!'"

5.3

command -v cowsay >/dev/null 2>&1 || sudo apt-get install -y cowsay

5.4

echo "PID-ul procesului părinte este: $" și "PPID-ul este: $(ps -p $ -o ppid=)"

2

This is my solution

5.1

git clone https://github.com/datablist/sample-csv-files.git

5.2

cd sample-csv-files
git log --pretty=format:"%h - %s" -n 3

5.3

awk -F, 'NR>=40 && NR<=70 {print $1":"$2":"$3}' files/people/people-100.csv

5.4

#!/bin/bash

if [ "$#" -ne 1 ]; then
echo "Utilizare: $0 adresa_de_email"
exit 1
fi

EMAIL=$1

FILE="files/people/people-10000.csv"

RESULT=$(grep -n "$EMAIL" "$FILE")

if [ -z "$RESULT" ]; then
echo "Adresa de email '$EMAIL' nu a fost găsită."
else
echo "Date găsite: $RESULT"
fi

1

Here is my solution:

5.1

mkdir -p ~/student/my-app
cd ~/student/my-app
git init

5.2

echo "Hello, World!" > ~/student/my-app/hello.txt
cd ~/student/my-app
git add hello.txt
git commit -m "Added hello.txt with 'Hello, World!'"

5.3

command -v cowsay >/dev/null 2>&1 || sudo apt-get install -y cowsay

5.4

echo "PID-ul procesului părinte este: $" și "PPID-ul este: $(ps -p $ -o ppid=)"

2

雪花飘飘的天空 2024-11-22 05:04:02

这是我的解决方案:
6.1
尾-n 15 ~/.bash_history | 64 位 | sha256sum

6.2

#!/bin/bash

if [ "$#" -ne 1 ]; then
echo "Utilizare: $0 nume_utilizator"
exit 1
fi

USERNAME=$1

PASSWORD=$(openssl rand -base64 6 | tr -d 'A-Z+/=')

useradd -m $USERNAME

echo "$USERNAME:$PASSWORD" | chpasswd

echo "Utilizatorul '$USERNAME' a fost creat."
echo "Parola: $PASSWORD"

6.3

对于 {1..50} 中的 i; do echo“这是曼波第五号。”;完成> mambo_no_5.txt && openssl enc -aes-128-cbc -salt -in mambo_no_5.txt -out mambo_no_5.enc -k 你的密码
6.4
纳米 ~/.bashrc
导出 HISTSIZE=50
source ~/.bashrc

1

这是我的解决方案:
6.1
#!/bin/bash

sum=0
count=0

while true; do
  echo -n "Introduceți un număr (0 sau non-număr pentru a opri): "
  read num
  # Verificăm dacă inputul este un număr
  if [[ $num =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then
    if [ $num -eq 0 ]; then
      break
    fi
    sum=$(echo "$sum + $num" | bc)
    ((count++))
  else
    break
  fi
done

if [ $count -ne 0 ]; then
  average=$(echo "scale=2; $sum / $count" | bc)
  echo "Media aritmetică este: $average"
else
  echo "Nu s-au introdus numere valide."
fi

6.2
#!/bin/bash

if [ $# -eq 0 ]; then
  echo "Utilizare: $0 nume_utilizator"
  exit 1
fi

username=$1

if getent passwd "$username" > /dev/null 2>&1; then
  # Extragem UID-ul și shell-ul
  uid=$(getent passwd "$username" | cut -d: -f3)
  shell=$(getent passwd "$username" | cut -d: -f7)
  echo "Utilizator: $username, UID: $uid, Shell: $shell"
else
  echo "Eroare: Utilizatorul '$username' nu există."
fi

6.3

chmod +x nume_script.sh
sudo mv nume_script.sh /usr/local/bin

秀cu 别名

6.4

#!/bin/bash
if [ $# -eq 0 ]; then
  echo "Utilizare: $0 -u (utilizator curent) | -m (memorie liberă) | orice 
altceva (eroare)"
  exit 1
fi

case $1 in
  -u)
    echo "Utilizatorul curent este: $(whoami)"
    ;;
  -m)
    free -h | grep Mem | awk '{print "Memorie liberă: " $4}'
    ;;
  *)
    echo "Argument necunoscut. Utilizați -u pentru utilizatorul curent sau 
-m pentru memoria liberă."
    ;;
esac

2

This is my solution:
6.1
tail -n 15 ~/.bash_history | base64 | sha256sum

6.2

#!/bin/bash

if [ "$#" -ne 1 ]; then
echo "Utilizare: $0 nume_utilizator"
exit 1
fi

USERNAME=$1

PASSWORD=$(openssl rand -base64 6 | tr -d 'A-Z+/=')

useradd -m $USERNAME

echo "$USERNAME:$PASSWORD" | chpasswd

echo "Utilizatorul '$USERNAME' a fost creat."
echo "Parola: $PASSWORD"

6.3

for i in {1..50}; do echo "This is mambo no. 5."; done > mambo_no_5.txt && openssl enc -aes-128-cbc -salt -in mambo_no_5.txt -out mambo_no_5.enc -k yourpassword
6.4
nano ~/.bashrc
export HISTSIZE=50
source ~/.bashrc

1

Here is my solution:
6.1
#!/bin/bash

sum=0
count=0

while true; do
  echo -n "Introduceți un număr (0 sau non-număr pentru a opri): "
  read num
  # Verificăm dacă inputul este un număr
  if [[ $num =~ ^-?[0-9]+([.][0-9]+)?$ ]]; then
    if [ $num -eq 0 ]; then
      break
    fi
    sum=$(echo "$sum + $num" | bc)
    ((count++))
  else
    break
  fi
done

if [ $count -ne 0 ]; then
  average=$(echo "scale=2; $sum / $count" | bc)
  echo "Media aritmetică este: $average"
else
  echo "Nu s-au introdus numere valide."
fi

6.2
#!/bin/bash

if [ $# -eq 0 ]; then
  echo "Utilizare: $0 nume_utilizator"
  exit 1
fi

username=$1

if getent passwd "$username" > /dev/null 2>&1; then
  # Extragem UID-ul și shell-ul
  uid=$(getent passwd "$username" | cut -d: -f3)
  shell=$(getent passwd "$username" | cut -d: -f7)
  echo "Utilizator: $username, UID: $uid, Shell: $shell"
else
  echo "Eroare: Utilizatorul '$username' nu există."
fi

6.3

chmod +x nume_script.sh
sudo mv nume_script.sh /usr/local/bin

Sau cu alias

6.4

#!/bin/bash
if [ $# -eq 0 ]; then
  echo "Utilizare: $0 -u (utilizator curent) | -m (memorie liberă) | orice 
altceva (eroare)"
  exit 1
fi

case $1 in
  -u)
    echo "Utilizatorul curent este: $(whoami)"
    ;;
  -m)
    free -h | grep Mem | awk '{print "Memorie liberă: " $4}'
    ;;
  *)
    echo "Argument necunoscut. Utilizați -u pentru utilizatorul curent sau 
-m pentru memoria liberă."
    ;;
esac

2

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文