【问题标题】:bash palindrome grep loop if then else missing 'bash 回文 grep 循环 if then else 缺失 '
【发布时间】:2014-10-31 22:26:54
【问题描述】:

我的系统管理员教授刚开始教我们 bash,他希望我们使用 grep 编写一个 bash 脚本,以便在不使用反向的情况下在 linux 字典中查找所有 3-45 个字母的回文。我的 if 语句出现错误,说我错过了一个'

更新代码:

    front='\([a-z]\)'
front_s='\([a-z]\)'
numcheck=1
back='\1'
middle='[a-z]'
count=3

while [ $count -ne "45" ]; do

    if [[ $(($count % 2)) == 0 ]]
        then
            front=$front$front_s
            back=+"\\$numcheck$back"
            grep "^$front$back$" /usr/share/dict/words
            count=$((count+1))
        else
            grep "^$front$middle$back$" /usr/share/dict/words

            numcheck=$((numcheck+1))
            count=$((count+1))
    fi

done

【问题讨论】:

  • 从“if”行中删除“:”(或用“;”代替)。此外,使用 if [[ ... ]](双括号)。同样在“while”行中..
  • 所以你和 Greg 有同一个教授(或者你的教授和他使用的是同一本书):stackoverflow.com/questions/26601234/bash-palindrome-checker
  • 再次感谢 arun,但我的脚本与他的不同。我认为我接近让它运行了。有什么意见吗?
  • 如果您的 ?是在单词文件(在Linux / Unix中)中找到所有从长度3到45的单词,这些单词是回文......并且你不必使用“rev”(反向)函数,然后看看我的答案,因为这就是你所需要的.你可以比我更好地对齐它。我使用了“[[:alnum:]]”,因为它可以搜索/工作以下词:P2P。但是,如果你想要更多的控制(比如 P2p 应该被视为回文),那么使用: w="$(echo $w | tr [A-Z] [a-z])";在 for 循环内(就在单词“do”之后和单词“if”之前。

标签: linux bash if-statement grep


【解决方案1】:

这里有四个明显的问题:

  • 首先关于一个错位且未转义的反斜杠:

    back="\\$numcheck$back" # and not back="$numcheck\$back"
    
  • 其次,如果count 是奇数,您只想增加numcheck
  • 第三:在行

     front=$front$front
    

    您将front 中的模式数量加倍!嘿,这会产生指数增长,因此爆炸 参数列表太长。要解决这个问题:添加一个变量,例如 front_step:

    front_step='\([a-z]\)'
    front=$front_step
    

    当你增加front:

    front=$front$front_step
    

这些都修好了,你应该就好了!

第四个缺陷是grep的反向引用可能只有一位:来自man grep

Back References and Subexpressions
   The back-reference \n, where n is a single digit, matches the substring
   previously  matched  by  the  nth  parenthesized  subexpression  of the
   regular expression.

在您的方法中,我们最多需要 22 个反向引用。这对grep 来说太过分了。不过,我怀疑有没有这么长的回文。

另外,你 grep 文件 43 次……这有点太多了。

【讨论】:

  • 感谢 gniourf,我做了你的修改,但在第 23 + 27 行仍然出现错误“/bin/grep: Argument list too long”
  • 是的,我现在找到了.. 一旦计数器变为 -gt 22,他应该停止放置 front=$front$front
  • 同意front_step变量法。
  • 感谢你们的出色编辑,尽管我的代码似乎仍然无法正常工作。它只打印 3 个字母回文。查看我更新的代码
  • @ConnerNey 好吧,back=+"\\$numcheck$back" 行中有一个 + 字符。删除它,它应该可以工作。
【解决方案2】:

试试这个:

#!/bin/bash

 for w in `grep -E "^[[:alnum:]]{3,45}$" /usr/share/dict/words`; do if [[ "$w" == "`echo $w|sed "s/\(.\)/\1\n/g"|tac|tr -d '\012'`" ]]; then echo "$w == is a palindrome"; fi; done

#!/bin/bash

front='\([a-z]\)'
numcheck=1
back='\1'
middle='[a-z]'
count=3

while [ $count -ne "45" ]; do

    if [[ $(($count % 2)) == 0 ]]
        then
            front=$front$front
            back="\\$numcheck$back"
            grep "^$front$back$" /usr/share/dict/words
        else
            grep "^$front$middle$back$" /usr/share/dict/words

            ## Thanks to gniourf for catching this.
            numcheck=$((numcheck+1))
    fi

    count=$((count+1))
    ## Uncomment the following if you want to see one by one and run script using bash -x filename.sh
    #echo Press any key to continue: ; read toratora;

done

【讨论】:

  • 再次感谢 Arun,但我必须保留这种格式的脚本。我今天在办公时间看到他,说这几乎正是他想要的。它只需要运行。因此,对我的代码进行任何添加/减少都会有帮助。再次感谢
  • 如果您使用“bash -x yourscript.sh”运行脚本,您就会知道为什么会看到该错误消息(太长...)。您的变量在脚本中没有做任何事情(因为您可以在使用单引号 ' ' 的 grep 命令中使用 $var ,模式也不适用于单引号。
  • 您可以在 grep 命令中给出的模式大小有一个限制。你不能给:grep "something_longer_than_universe_size_pattern" 单词文件。当我过去遇到类似的问题时,我不得不将模式部分放在另一个文件中,并且必须使用“fgrep”命令。
  • 不确定你的意思,我在 ubuntu 终端中使用 rbash myfile.sh 运行它
  • 我确实理解可变大小,并且认为 id 遇到了这个问题。
猜你喜欢
  • 2014-06-07
  • 1970-01-01
  • 2014-03-25
  • 1970-01-01
  • 1970-01-01
  • 2021-08-10
  • 1970-01-01
  • 2022-08-02
  • 2016-07-23
相关资源
最近更新 更多