grep 一个变量并向其添加 1

grep 一个变量并向其添加 1

我有一个包含前导零数字的变量,我想 grep 这个变量和同一个变量加一。我做了几次尝试,但遇到了错误。这就是我想做的:

read var
newvar=$(($var +1))
grep '$var' /some/dir
grep '$newvar' /some/dir

我真的认为我的代码有问题。我也尝试过一些这样的测试:

#!/bin/bash
echo "enter number"
read number
newnumber=$(($number + 1))
echo "$newnumber"

这给了我一个错误:value too great for base (error token is。如果我这样做:

 #!/bin/bash
echo "enter number"
read number
number=""
newnumber=$(($number + 1))
echo "$newnumber"

这将始终输出 1。

我的尝试出了什么问题,我该如何做我想做的事?

答案1

您使用了错误的引号:单引号会阻止表达式''的扩展( and以及旧形式)。请改用双引号。尽管在这种情况下,如果您确定它是一个数字,那么您不需要$$var$(command)`command`""任何引号。

对于你的第二个问题......你使用前导零吗?这表示八进制,因此数字89不起作用。

答案2

极客龙已经解释了为什么你的第一次尝试失败了。以下是有关您尝试执行的操作的一些其他提示。

如果您正在寻找类似 的数字42,您可能想要匹配042,但不想匹配1042421。要实现这一目标,您所需要的只是一个更高级的正则表达式。假设$newnumber包含没有前导零的数字(整数、正数、十进制表示形式),则查找$newnumber前面是行首或非数字字符的字符,后面同样如此。0*进一步允许前导零。该-E选项表明grep您正在使用现代正则表达式语法(而不是历史语法,后者更奇怪且功能更弱)。

grep -E "(^|[^0-9])0*$newnumber(\$|^[0-9])" /path/to/file

要在 bash 中解析带有潜在前导零的数字,您可以使用$((10#$newnumber))强制进行十进制解释。在其他 shell 中,情况稍微复杂一些;有一个 shell 构造可以获取没有特定前缀的变量的值${var#prefix},还有一个类似的后缀构造${var%suffix},但是没有办法指定“最长的可能0字符序列”作为要 strip 的前缀。但它可以分两步完成:首先获取var不是前导零的部分,并将其用作剥离的前缀。不是前导零的部分var是其以非零开头的最长后缀,即${var%%[!0]*}(双精度%表示取出与模式匹配的最长后缀;单精度%表示取出最短的后缀)。

read number
number=${number#${number%%[!0]*}}

进一步说明:grep REGEXP /some/file搜索单个文件/some/file。如果要搜索目录中的所有文件,请让 shell 生成文件列表:grep REGEXP /some/dir/*.如果要递归搜索目录及其子目录中的所有文件,请将选项传递-r给以grep使其递归:grep -r REGEXP /some/dir

答案3

正如 geekosaur 所说,您使用了错误的引号。当您希望 shell 将变量引用扩展为值时,请坚持使用双引号。

其次,你在双括号内的数学运算是错误的。您不希望其中有 $,$(( )) 构造内的变量引用不需要 $。

#!/bin/bash
echo "enter number"
read number
newnumber=${number#${number%%[!0]*}}
newnumber=$((newnumber + 1))
echo "$number changes to $newnumber"

这两个更改在你的原版中也对我有用......

read var
newvar=${var#${var%%[!0]*}}
newvar=$((newvar + 1))
printf -v newvar "%02d" "$newvar"
grep "$newvar" /some/dir

更新添加了printf格式化输出的行。 更新2添加了用于输入零填充数字的修复。现在这应该是一个完整的例子了。

答案4

一堆部分答案:

如何处理带有前导零的数字 v1:

newvar=$(printf '%s + 1\n' "$var" | bc)

或者,等价地,

newvar=$(bc <<< "$var + 1")

因为bc不将带有前导零的数字视为八进制。

据我所知,这不会造成代码注入漏洞,因为bc似乎没有 shell 转义功能。 (我可能忽略了一些东西。)请注意,这个问题并没有说“仅 bash”。

如何处理带有前导零的数字 v2:

newvar=$((1$var - 10000 + 1))

显然,这使用了一个技巧,姚莉想做的事: 通过1前置0042 作为字符串操作, 您将得到 string 10042,该字符串被处理为十进制数。请注意,在此构造中,您必须包含 $in$var  以使 the1和 the $var 被解析为两个单独的单元(然后连接)。

如果已知输入值的长度为四位数字(例如 0042),请按原样使用上述命令。如果它们有其他长度(提前已知),请将10000上面的 更改为1后跟适当数量的零。

如果你提前知道长度,做

pow10="1$(printf "%0${#var}d" 0)"

或者

pow10="1$(printf '%0*d' "${#var}" 0)"

如果数字是四位数字长(例如,  0042),这些基本上用于printf '%04d' 0生成0000,然后在前面加上 a 1以获得 10000。然后做

newvar=$((1$var - pow10 + 1))

如何向newvar结果添加前导零:

马克的回答表明您可以使用

printf -v newvar '%04d' "$newvar"

或者,等价地,

newvar=$(printf '%04d' "$newvar")

添加足够的前导零,使其$newvar总数达到四位数。如果您事先不知道长度,可以使用上一节中的技术:

newvar="$(printf "%0${#var}d" "$newvar")"

或者

newvar="$(printf '%0*d' "${#var}" "$newvar")"

相关内容