BASH回文检查器
这是我第一次在这里发帖,请容忍我 我收到了一份bash作业,但我的教授和他的笔记都毫无用处 我们的任务是从文件中过滤并打印回文。在本例中,目录为:BASH回文检查器,bash,loops,grep,palindrome,Bash,Loops,Grep,Palindrome,这是我第一次在这里发帖,请容忍我 我收到了一份bash作业,但我的教授和他的笔记都毫无用处 我们的任务是从文件中过滤并打印回文。在本例中,目录为: /usr/share/dict/words 单词长度从3到45不等,应该只过滤小写字母(给定的词典包含字符和大写字母以及小写字母)。i、 所以像“q-evvavve-q”这样的东西可以算作回文,但我不应该得到一个正确的结果 无论如何,我可以让它过滤掉x个单词并返回(而不是只过滤小写) 我可以用后面的行来表示5个字母的单词和7个字母的单词,以此类推:
/usr/share/dict/words
单词长度从3到45不等,应该只过滤小写字母(给定的词典包含字符和大写字母以及小写字母)。i、 所以像“q-evvavve-q”这样的东西可以算作回文,但我不应该得到一个正确的结果
无论如何,我可以让它过滤掉x个单词并返回(而不是只过滤小写)
我可以用后面的行来表示5个字母的单词和7个字母的单词,以此类推:
grep "^.....$" /usr/share/dict/words |
grep "\(.\)\(.\).\2\1"
但教授不希望这样。我们应该使用一个循环。我知道这个概念,但我不知道语法,就像我说的,这些注释是毫无帮助的
我尝试的是设置变量x=。。。和y=。。在一个while循环中,使用x=$x$y,但这不起作用(语法错误),x+=
感谢您的帮助。甚至把我的非小写字母过滤掉
谢谢
编辑:
如果要提供解决方案或解决方案的提示,最好使用最简单的方法。
最好是使用2个grep语句和一个循环的
再次感谢。好的,这里有一些东西可以帮助您开始: 我建议使用上面的计划,只需使用for循环生成“.”的数量 此问题将解释如何从3到45进行for循环: 现在你只需要弄清楚如何在你的第一个grep中生成“i”个点数,你就完成了
此外,查看sed,它可以为您生成非小写的答案 好的,这里有一些东西可以让你开始: 我建议使用上面的计划,只需使用for循环生成“.”的数量 此问题将解释如何从3到45进行for循环: 现在你只需要弄清楚如何在你的第一个grep中生成“i”个点数,你就完成了 此外,查看sed,它可以为您生成非小写的答案 像这样:
for word in `grep -E '^[a-z]{3,45}$' /usr/share/dict/words`;
do [ $word == `echo $word | rev` ] && echo $word;
done;
使用我的字典输出:
aha
bib
bob
boob
...
wow
更新
正如评论中指出的,在大多数字典中读入for循环中的变量可能不是最有效的,并且有可能在某些shell中触发错误。以下是更新版本:
grep -E '^[a-z]{3,45}$' /usr/share/dict/words | while read -r word;
do [ $word == `echo $word | rev` ] && echo $word;
done;
像这样:
for word in `grep -E '^[a-z]{3,45}$' /usr/share/dict/words`;
do [ $word == `echo $word | rev` ] && echo $word;
done;
使用我的字典输出:
aha
bib
bob
boob
...
wow
更新
正如评论中指出的,在大多数字典中读入for循环中的变量可能不是最有效的,并且有可能在某些shell中触发错误。以下是更新版本:
grep -E '^[a-z]{3,45}$' /usr/share/dict/words | while read -r word;
do [ $word == `echo $word | rev` ] && echo $word;
done;
多个
grep
s是浪费。你可以简单地做
grep -E '^([a-z])[a-z]\1$' /usr/share/dict/words
一下子,同样地,将表达式放在grep
的标准输入上,如下所示:
echo '^([a-z])[a-z]\1$
^([a-z])([a-z])\2\1$
^([a-z])([a-z])[a-z]\2\1$' | grep -E -f - /usr/share/dict/words
但是,常规的grep
不允许超出\9
范围的反向引用。使用grep-P
也可以使用两位数的反向引用
以下脚本在循环中构造整个表达式。不幸的是,grep-P
不允许使用-f
选项,因此我们构建了一个大thumpin'变量来保存模式。然后,我们实际上也可以简化为一个形式为^(.)(?:.|(.)(?:.|(..)…\3)?\2?\1$
,除了我们使用[a-z]
而不是
来限制为小写之外
head=''
tail=''
for i in $(seq 1 22); do
head="$head([a-z])(?:[a-z]|"
tail="\\$i${tail:+)?}$tail"
done
grep -P "^${head%|})?$tail$" /usr/share/dict/words
单个grep
应该比在大型输入文件上单独调用grep
22或43次快得多。如果您想按长度排序,只需将其作为过滤器添加到管道的末尾;它应该仍然比在整个字典上多次调用快得多
表达式
${tail+:)?}
只有在tail
为非空时才计算为右括号和问号,这是强制\1
返回引用为非可选的方便方法。类似地,${head%|}
从$head
的最终值修剪最终的交替运算符。多个grep
都是浪费。你可以简单地做
grep -E '^([a-z])[a-z]\1$' /usr/share/dict/words
一下子,同样地,将表达式放在grep
的标准输入上,如下所示:
echo '^([a-z])[a-z]\1$
^([a-z])([a-z])\2\1$
^([a-z])([a-z])[a-z]\2\1$' | grep -E -f - /usr/share/dict/words
但是,常规的grep
不允许超出\9
范围的反向引用。使用grep-P
也可以使用两位数的反向引用
以下脚本在循环中构造整个表达式。不幸的是,grep-P
不允许使用-f
选项,因此我们构建了一个大thumpin'变量来保存模式。然后,我们实际上也可以简化为一个形式为^(.)(?:.|(.)(?:.|(..)…\3)?\2?\1$
,除了我们使用[a-z]
而不是
来限制为小写之外
head=''
tail=''
for i in $(seq 1 22); do
head="$head([a-z])(?:[a-z]|"
tail="\\$i${tail:+)?}$tail"
done
grep -P "^${head%|})?$tail$" /usr/share/dict/words
单个grep
应该比在大型输入文件上单独调用grep
22或43次快得多。如果您想按长度排序,只需将其作为过滤器添加到管道的末尾;它应该仍然比在整个字典上多次调用快得多
表达式
${tail+:)?}
只有在tail
为非空时才计算为右括号和问号,这是强制\1
返回引用为非可选的方便方法。类似地,${head%|}
从$head
的最终值修剪最后的交替运算符,为什么使用grep
?Bash很乐意为您这样做:
#!/bin/bash
is_pal() {
local w=$1
while (( ${#w} > 1 )); do
[[ ${w:0:1} = ${w: -1} ]] || return 1
w=${w:1:-1}
done
}
while read word; do
is_pal "$word" && echo "$word"
done
将此保存为banana
,chmod+x banana
,然后享受:
./banana < /usr/share/dict/words
如果只希望保留仅包含小写字母且至少包含三个字母的单词:
grep '^[[:lower:]]\{3,\}$' /usr/share/dict/words | ./banana
为什么要使用
grep
?Bash很乐意为您这样做:
#!/bin/bash
is_pal() {
local w=$1
while (( ${#w} > 1 )); do
[[ ${w:0:1} = ${w: -1} ]] || return 1
w=${w:1:-1}
done
}
while read word; do
is_pal "$word" && echo "$word"
done
萨瓦