linux bash 中的 sscanf 等价物

sscanf equivalent in linux bash

我想提取出现在 linux 脚本中间的数字 bash:

APPLES_STR="We have 123 apples."
NUM=?????

在 C 中我会做类似的事情:

int num;
const char *str = "We have 123 apples."
sscanf(str, "We have %d apples.", &num);

如何在 linux bash 中做到这一点?

使用 bash 和正则表达式:

sscanf() {
  local str=""
  local format=""
  [[ "$str" =~ $format ]]
}

sscanf "We have 123 apples and 42 peaches." "We have (.*) apples and (.*) peaches."

您将在字段 1 的数组 BASH_REMATCH 中找到匹配项。

echo "${BASH_REMATCH[1]}"
echo "${BASH_REMATCH[2]}"

输出:

123
42

另一种接近 sscanf() 的方法是传入正则表达式类型模式进行匹配,然后使用 +(...) extglob 模式将输入字符串中的所有匹配项替换为 "(.*)" 然后让 [[ .. =~ .. ]] 填充 BASH_REMATCH,而不必传递带有手动插入的 "(.*)" 的字符串副本。例如:

#!/bin/bash

shopt -s extglob

sscanf () {
    local regex=""
    local str="${1//+(${regex})/(.*)}"
    [[  =~ $str ]]
}

sscanf "We have 123 apples and 42 peaches." "[[:digit:]]"

declare -p BASH_REMATCH

这基本上就是@Cyrus 的出色回答所显示的内容,它只是构建搜索字符串的另一种方法。

示例输出

$ bash sscanf.sh
declare -ar BASH_REMATCH=([0]="We have 123 apples and 42 peaches." [1]="123" [2]="42")

(注:无耻地借用@Cyrus的示例文本)