【问题标题】:script in bash two if condition and print in for loopbash 两个 if 条件中的脚本并在 for 循环中打印
【发布时间】:2021-10-18 23:15:27
【问题描述】:

您好,我正在学习使用 bash 编写脚本,我正在尝试解决一个小练习。 练习是这样的

如果名为“basenew”的变量包含变量的内容 命名为“价值基础”。 “basenew”必须包含超过 113,469 人物。如果两个条件都满足,那么脚本必须打印 变量“basenew”的最后 20 个字符。

我的代码是

#!/bin/bash

basenew="8dm7KsjU28B7v621Jls"
valuebase="ERmFRMVZ0U2paTlJYTkxDZz09Cg"

for i in {1..40}
do
    basenew=$(echo $basenew | base64)

    if [[ $basenew =~ $valuebase && ${#basenew} -ge 113469 ]] ; then
        echo $i
        echo $basenew | wc -c
        StrLen=`echo ${basenew} | wc -c`
        From=`expr $StrLen - 20`
        echo $basenew | cut -c ${From}-${StrLen}
    else
        echo "error"

    fi
done

但我卡住了,因为在循环 28 中打印,并且是最后 20 个但不是正确答案。

对使用 tail -c 20 打印最后 20 个字符有什么建议吗?

谢谢

【问题讨论】:

  • 或许"${basenew: -20: 20}" (gnu.org/software/bash/manual/html_node/…)
  • 我尝试但在此代码中给出相同的输出StrLen=`echo ${basenew} | wc -c` From=`expr $StrLen - 20` echo $basenew | cut -c ${From}-${StrLen}
  • @joop: "basenew" 包含...名为“valuebase”的变量 在您的示例中,basenew 比 valuebase 短,更长的字符串永远不能包含更短的一,所以你应该期待 error 在这里。
  • @joop:变量总是只包含字母和数字吗?如果它们可以包含特殊字符,您的方法可能会完全失败,因为=~ 的右侧被视为正则表达式。您应该测试子字符串,而不是正则表达式匹配。
  • 在内存中保留大量数据通常是一个糟糕的设计,而且通常很容易避免。

标签: bash for-loop if-statement tail


【解决方案1】:

关于使用 tail 打印最后 20 个字符的任何建议

来自tail 手册页:

   -c, --bytes=[+]NUM
         output the last NUM bytes; or use -c +NUM to output  starting  with
         byte NUM of each file

因此,如果您有一个变量 x,您可以使用它的最后 20 个字符打印到标准输出

tail --bytes=20 <<<$x

【讨论】:

    【解决方案2】:

    为什么您认为basenew 的值会在循环执行期间发生变化?你永远不会分配它。但是您分配了从未使用过的var,这可能是问题吗?是的,您需要更新basenew,而不是未使用的var

    您的脚本还有另一个问题:cut 将您的字符选择应用于输入的每一行。 base64,默认情况下,将输出拆分为 76 个字符的行。所以,过了一会儿,你有很多短线。由于它们都比您的规范短得多,cut 只会打印很多换行符,而不是字符串的最后 20 个字符。你可以用base64 -w0 改变base64 的行为,但它也会改变每次迭代的结果,你可能永远不会匹配引用字符串。

    按照 joop 的建议,不要在 cut 中使用管道 echo"${basenew: -20: 20}" 扩展为 basenew 值的最后 20 个字符。或者,更简单但等效:"${basenew: -20}"。不要忘记:-20 之间的空格,它是必需的。

    最后,您可以使用更多内置的 bash 结构来避免外部命令(wcechocut),使用现代的 $(...) 而不是旧的反引号,并使用算术评估 ( ((...))) 而不是过时的 expr。试试吧,也许:

    #!/usr/bin/env bash
    
    # file: foo.sh
    
    basenew="8dm7KsjU28B7v621Jls"
    valuebase="ERmFRMVZ0U2paTlJYTkxDZz09Cg"
    
    for i in {1..40}; do
        basenew=$(echo "$basenew" | base64)
        if [[ $basenew =~ $valuebase ]] && (( ${#basenew} >= 113469 )) ; then
            printf '%d\n%d\n%s\n' "$i" "${#basenew}" "${basenew: -20}"
        else
            printf 'error\n'
        fi
    done
    

    演示:

    $ ./foo.sh
    error
    ...
    error
    28
    113469
    U2paTlJYTkxDZz09Cg==
    error
    ...
    error
    

    【讨论】:

    • 我尝试了代码,但我得到了相同的输出,而且练习让我觉得输出错误。有什么方法可以将 28 轮保存在 .txt 中的循环中?
    • 我刚刚对其进行了测试,结果完全符合您的预期。您是否真的复制粘贴了整个脚本并运行了这个,而不是另一个?是的,有一种方法可以将basenew 的连续值存储在一个文件中。只需在basenew=$(echo "$basenew" | base64) 之后添加echo "$basenew" &gt; "$i.txt"。然后查找1.txt2.txt...文件
    • 是的,我尝试了您发布的代码,这就是为什么我不明白,因为遇到了两个 if。我在练习中得到的唯一提示是使用 tail -c 20,但这是相同的功能"${basenew: -20}"
    • 当你写“i get the same output”时,你的意思是你看到了40次error而不是27次error,然后是28,@ 987654354@, U2paTlJYTkxDZz09Cg== 和 12 次 error?
    • "我在练习中得到的唯一提示是使用 tail -c 20,但这会产生相同的函数“${basenew: -20}”:不是完全正确。如果您尝试echo "$basenew" | tail -c 20,您将得到2paTlJYTkxDZz09Cg== 加上换行符,而不是U2paTlJYTkxDZz09Cg==。您的规范是什么?打印最后20 个字符,包括最后一个换行符还是不包括最后一个换行符?
    猜你喜欢
    • 2023-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多