如何在特定索引处获取字符串的字符?

时间:2014-09-14 18:54:42

标签: linux string bash

我正在尝试编写一个脚本,用户输入一个数字作为参数,脚本计算所有数字的总和,例如。,

    ./myScript 963
    18

因此脚本获取字符串“963”并添加字符串9+6+3=18中的所有字符。我想我可以得到字符串的长度并使用循环将字符串的所有索引添加到一起但我无法弄清楚如何在不知道你正在寻找的字符的情况下获取字符串的索引。 / p>

我能够使用以下命令

打破字符串
    echo "963" | fold -w1
    9
    6
    3

但我不确定是否/如何我可以管道|或将结果重定向>并将其每次添加到总计中。

如何在特定索引处获取字符串的字符?

更新

示例1:

$ 1 = 59然后操作是 5 + 9 = 14

示例2:

$ 1 = 2222然后操作是 2 + 2 + 2 + 2 = 8

字符串中的所有字符都会加到总和中。

6 个答案:

答案 0 :(得分:4)

以下脚本遍历输入字符串中的所有数字并将它们一起添加:

#!/bin/bash

s="$1"

for ((i=0; i<${#s}; ++i)); do
    ((t+=${s:i:1}))
done

echo "sum of digits: $t"

语法${s:i:1}从字符串i中的位置$s中提取长度为1的子字符串。

输出:

$ ./add.sh 963
sum of digits: 18 

如果你想继续将数字加在一起,直到剩下的只有一个,你可以这样做:

#!/bin/bash

s="$1"

while (( ${#s} > 1 )); do
    t=0
    for ((i=0; i<${#s}; ++i)); do
        ((t+=${s:i:1}))
    done
    echo "iteration $((++n)): $t"
    s=$t
done   
echo "final result: $s"

只要字符串的长度大于1,外部while循环就会继续。内部for循环将字符串中的每个数字加在一起。

输出:

$ ./add.sh 963
iteration 1: 18
iteration 2: 9
final result: 9 

并非您要求它,但有很多方法可以对字符串中的所有数字求和。这是使用Perl的另一个:

$ perl -MList::Util=sum -F -anE 'say sum @F' <<<639
18

List::Util是Perl的核心模块。 sum子例程对列表执行减少求和以生成单个值。 -a启用自动拆分模式,因此输入将拆分为数组@F-F用于设置字段分隔符(在这种情况下,它是空白的,因此每个字符都算作一个单独的字段)。 -n一次处理一行输入,-E用于输入Perl单行,但启用了较新的功能(例如say)。 sayprint类似,但输出中会添加换行符。

如果您不熟悉<<<语法,则相当于echo 639 | perl ...

答案 1 :(得分:1)

不使用字符串订阅,而是计算所需的总和:

number=963
sum=0
for d in `echo "$number" | sed 's,\(.\), \1,g'`
do
    sum=$(($sum + $d))
done
echo $sum

输出:18

答案 2 :(得分:1)

我会这样做:

num="963"
echo "$num" | grep -o . | paste -sd+ - | bc

#or using your fold
echo "$num" | fold -w1 | paste -sd+ - | bc

都打印

18

解释

  • grep -o .会返回您号码中的每个数字以及fold -w1
  • paste -sd+ -使用分隔符+将线条合并为一行 - 例如创建一个像9+6+3
  • 这样的计算字符串
  • bc进行计算

如果你想要脚本,例如digadd.sh使用

grep -o . <<<"$1" | paste -sd+ - | bc

使用它

$ bash digadd.sh             #nothing
$ #will return nothing

$ bash digadd.sh 1273617617273450359345873647586378242349239471289638982
268
$

为了好玩,在循环中执行此操作直到结果只有1位数

num=12938932923849028940802934092840924
while [[ ${#num} > 1 ]]
do
    echo -n "sum of digits for $num is:"
    num=$(echo "$num" | grep -o . | paste -sd+ - | bc)
    echo $num
done
echo "final result: $num"

打印

sum of digits for 12938932923849028940802934092840924 is:159
sum of digits for 159 is:15
sum of digits for 15 is:6
final result: 6

另一个有趣的变体,将从任何字符串中提取所有数字的内容是:

grep -oP '\d' <<<"$1" | paste -sd+ - | bc

所以在脚本digadd.sh中使用它

bash digadd.sh 9q6w3

产生

18

标题中您的问题的答案:要从任何字符串中获取第N个字符,您可以使用

echo "$string:POSITION:length"  #position from 0

e.g。获得第一位数

echo "${num:0:1}"

答案 3 :(得分:0)

您可以使用cut -c参数来获取任意位置的角色。例如:

echo "963" | cut -c1

输出:9

答案 4 :(得分:0)

使用awk

awk 'split($0,a,""){for(i in a) sum+=i}END{print sum}' <<<$1

答案 5 :(得分:0)

这可以使用子串操作完成(由busybox ash支持,但不符合posix sh)

#!/bin/ash
i=0
sum=0
while [ $i -lt ${#1} ]; do
  sum=$((sum+${1:i:1}));
  i=$((i+1))
done
echo $sum

如果你真的必须有一个posix shell兼容版本,你可以使用:

#!/bin/sh
sum=0
A=$1

while [ ${#B} -lt ${#A} ];do
  B=$B?
done

while [ "$A" ]; do
  B=${B#?*}
  sum=$((sum+${A%$B}))
  A=${A#?*}
done

echo $sum