我们如何去检验是否存在回文

sed命令能够记住匹配的子样式,称为反向引用,我们可以按照这个方式来解决回文问题

sed -n ‘/\(.\)\1/p’ filename

\()\的作用是记录()中的子串,上面的语句中还有一个. 是sed用于匹配单个字符的正则表达式

\1 对应() 中匹配的第一处内容, \2对应第二处匹配,因此我们就记录多个() 所匹配的内容 ()以\(\)的形式出现,表明不是普通的字符

sed会打印出.替换的正则表达式的字符两次

那么多回文,可能出现具有奇数个字符的情况,包含奇数长度的回文的正则表达式类似如下的形式,

‘/\(.\).\1/p’

我们额外加了一个字符 .

我们来编写这个回文脚本

if [$# -ne 2];

then

echo “Usage: $0 filename string_lenth”

exit -1

fi

filename=$1

basepattern=’/^\(.\)’

count=$(($2/2))

for((i=1;i<$count;i++))

do

basepattern=$basepattern’\(.\)’;

done

if [ $(( $2 % 2)) -ne 0 ];

then

basepattern=$basepattern ‘.’ ;

fi

for((count;count>0;count–))

do

basepattern=$basepattern’\'”$count” ;

done

basepattern=$basepattern’$/p’

sed -n “$basepattern” $filename

这样这个脚本可以直接使用了

具体的原理在于

想要匹配一个字符,并且进行反向的引用

使用 \(.\) 匹配单个字符,在用\1引用

匹配双字节,使用

sed ‘/\(.\)\1/p’

为了指明必须从行首开始匹配,我们加入了行首的标记

于是,上面的命令变为了sed ‘/^\(.\)\1/p’ /p可以帮助我们打印匹配的内容

匹配4个字符的回文

sed ‘/^\(.\)\(.\)\2\1/p’

我们用了2个 \(.\) 匹配记录回文中前两个字符, \2 \1会进行反向的引用

上面的脚本中,使用了一个被称为 basepattern的变量,包含了用于sed脚本的部分内容

basepattern最初初始化为basepattern=’/^\(.\)’ 对应匹配一个单字符, for循环拼接 \(.\)和baseoattern

循环的次数是回文长度的一般,最后,为了支持奇数长度的回文,在正则表达式和反向引用之间加上了一个可选的字符 (.)

这样,创建用于匹配回文的sed匹配的样式,这个匹配样式可以用来从字典文件中找出回文

我们使用for循环生成sed匹配样式,其实sed还可以自动的生成,但是有点难理解

于是先行暂停

获取到一个文本的倒序,其实unix提供了一个单独的rev的命令,

rev命令接收一个文件或者stdin作为输入,并且逆序打印出每一行的内容

比如,我们进行逆序的打印

string=”malayalam”

if[[ “String”==”$(echo $string | rev)” ]];

then

echo “Palidrome”

else

echo ‘Not palindrome”

fi

rev将所有的单词进行翻转

利用rev和tac的合作

sentence=’this is line from sentence’

echo $sentence | rev | tr ‘ ‘ ‘\n’ | tac |tr ‘\n’ ‘ ‘ | rev

上面的命令,首先使用了rev来翻转所有的字符,然后使用tr将空格替换为 \n,这样,所有的单词就分割为了单一的行,然后通过tac将所有的行进行翻转,然后tr将翻转的行合并为单一的行

最后对合并后的单行,再一次的rev,实现了翻转

发表评论

邮箱地址不会被公开。 必填项已用*标注