在bash / sed中,如何匹配小写字母和大写的SAME字母?

时间:2018-12-11 17:13:44

标签: regex bash sed

我想从输入字符串中删除“ aA”,“ bB” ...“ zZ”的所有实例。

例如

echo "foObar" |
sed -Ee 's/([a-z])\U\1//'

应输出"fbar"

但是\ U语法在sed表达式的后半部分(替换部分)中起作用-无法在匹配子句中解析。

我很难将匹配的字符转换为大写以在匹配子句中重用。


如果有人建议使用可以在sed(或awk)中使用的正则表达式,那就太好了。

使用纯shell编写脚本解决方案也是可以的(我正在尝试以这种方式解决问题)。

工作PCRE(与Perl兼容的正则表达式)也可以,但是我不知道它们如何工作,因此,如果您能提供一个解释来回答问题,那就太好了。

不幸的是,我没有在使用的机器上安装perl或python。

5 个答案:

答案 0 :(得分:3)

您可以使用以下perl解决方案:

echo "foObar" | perl -pe 's/([a-z])(?!\1)(?i:\1)//g'

请参见online demo

详细信息

  • ([a-z])-第1组:小写ASCII字母
  • (?!\1)-如果下一个字符与用组1捕获的字符相同,则负匹配将使匹配失败
  • (?i:\1)-与第1组捕获的字符相同,但在不同情况下(由于之前的超前查找)。

-e选项允许您定义要由编译器执行的Perl代码,而-p选项始终在循环中每次输出$_的内容。参见more here

答案 1 :(得分:3)

这可能对您有用(GNU sed):

sed -r 's/aA|bB|cC|dD|eE|fF|gG|hH|iI|jJ|kK|lL|mM|nN|oO|pP|qQ|rR|sS|tT|uU|vV|wW|xX|yY|zZ//g' file

编程解决方案:

sed 's/[[:lower:]][[:upper:]]/\n&/g;s/\n\(.\)\1//ig;s/\n//g' file

这会标记所有成对的小写字符,后跟一个大写字符并带有换行符。然后,将所有由后向引用匹配的标记和配对全部删除,而不管大小写如何。删除所有其他换行符,从而使不相同的对保持不变。

答案 2 :(得分:2)

这是一个详细的awk解决方案,因为OP没有可用的perlpython

echo "foObar" |
awk -v ORS= -v FS='' '{
   for (i=2; i<=NF; i++) {
      if ($(i-1) == tolower($i) && $i ~ /[A-Z]/ && $(i-1) ~ /[a-z]/) {
         i++
         continue
      }
      print $(i-1)
   }
   print $(i-1)
}'

fbar

答案 3 :(得分:1)

注意:根据OP的反馈,此解决方案很慢(毫不奇怪):
“不幸的是,由于多次通过-它使速度变慢。”


如果您知道某个字符序列¹永远不会出现在输入中,
您可以使用sed使用三阶段替换来完成此操作:

echo 'foObar foobAr' | sed -E -e 's/([a-z])([A-Z])/KEYWORD\1\l\2/g' -e 's/KEYWORD(.)\1//g' -e 's/KEYWORD(.)(.)/\1\u\2/g'

给您:fbar foobAr

替换阶段说明:

  • 查找小写字母后跟任何大写字母,然后将两个字母都替换为小写,并在其前面加上关键字foObar foobAr-> fKEYWORDoobar fooKEYWORDbar
  • 删除关键字,后跟两个相同字符(现在均为小写,因此后向引用有效)fKEYWORDoobar fooKEYWORDbar-> fbar fooKEYWORDbar
  • 从输出中剥离剩余的²关键字,并将其后的第二个字符转换回其原始大写版本fbar fooKEYWORDbar-> fbar foobAr

¹在此示例中,我使用KEYWORD进行演示。单个字符或至少较短的字符序列会更好/更快。只需确保选择输入中永远不可能出现的内容即可。
²剩余的字母是小写字母 不相同的情况,因此我们必须将它们恢复为原始状态

答案 4 :(得分:1)

有一个简单的词法,

%option main 8bit
    #include <ctype.h>
%%
[[:lower:]][[:upper:]] if ( toupper(yytext[0]) != yytext[1] ) ECHO;

(这是#include之前的标签,降价会丢失这些标签)。只需将其放在例如that.l,然后make that。 Easy-peasy lex是您工具包的不错补充。