regex - 使 sed 仅替换精确的字符串

标签 regex linux bash sed preg-match

我有一个像下面这样的 css 文件:

    #layout.one-column  #menu-secondary{background: #3c3c3c; height: 20px; font-family: 'Trebuchet MS'; font-weight: bold; font-size: 15px; padding: 10px;}     
    #layout.one-column  #menu-secondary a {color: #FFF; text-decoration: none;}
    #layout.one-column  #menu-secondary ul {}   
    #layout.one-column  #menu-secondary ul li {display: block; height: 30px; float: left; margin: 0 20px 0 0;}  
    .ofr h2 {font-size: 17px; height: 35px; margin: 0 10px 10px 10px;}  
    .ofr h2 a {color: #2a2a2a; text-decoration: none;}      
    #layout.one-column  #menu-secondary ul li.active {background: url(../img/selected.gif) no-repeat bottom center;}
    #layout.one-column  #menu-secondary ul li a {display: block; float: left; padding: 0 10px;}     
    #layout.one-column  #menu-secondary ul li a:hover {text-decoration: underline;}  

如您所见,每一行的开头都有制表符/一对空格,字符串以 .whatever/#whatever 开头。我编写了一个小脚本,该脚本在某一时刻运行:

find css/myCSS.css -name "*.css" -type f -exec sed -i "s/\<$pattern\>/$replacer/g" {} \;

其中 $pattern 可以是 #layout$replacer 可以是 #LAYOUT。我想做的是,如果字符串是

,我想做的是用 #LAYOUT 替换 #layout
  • 等于($pattern 前后的空格/制表符)
  • 等于($pattern 之前的空格/制表符)后跟 加上任何内容(#pattern.whatever)
  • 等于($pattern 之前的空格/制表符)后跟 # 加上任何内容(#pattern#whatever)
  • 喜欢#whatever.pattern 或#whatever#pattern(#whatever 之前和#pattern 之后的空格/制表符)。

我希望我现在做到了, Crystal 般清晰:)

这里有一些例子,每一行中的#pattern 或 .pattern 都应该被替换:

#pattern     <- blank spaces/tabs before and after the string  
#pattern.bar <- blank spaces/tabs before #pattern  and after .bar  
.pattern#bar <- blank spaces/tabs before .pattern  and after #bar  
#foo.pattern <- blank spaces/tabs before #foo and after .pattern  
.foo#pattern <- blank spaces/tabs before .foo and after #pattern  
.pattern     <- blank spaces/tabs before and after the string   

我一直在尝试使用 sed 来完成它,但我无法通过,并且认为对于每天使用 sed 工作的人来说我可能会“轻松”。再次感谢 :)

最佳答案

如果您想根据需要重新定义单词边界,则需要枚举它们。一种方法是,获取边界模式并将其附加到最后:

echo "well #menu not #menu-foo #menu" | sed -r 's/#menu([ \t\n\r.!?,]|$)/#MENU\1/g'
well #MENU not #menu-foo #MENU

|$是抓取文件结尾/输入案例结尾。

我仍然不知道前导 # 的作用,但我想如果您需要\1MENU\2 作为第一个分隔符模式,您可以应用这个想法。

更新 28.07,23:45:

  • 等于($pattern 前后的空白/制表符) [ \t]pattern[ \t]
  • 等于($pattern 之前的空白/制表符)后跟点加上任何内容(#pattern.whatever) [ \t]pattern.[^ \t]对“任何”的详尽描述会更好。额外的点,是 - 允许的 - 我们如何识别“无论什么”结束?空格?
  • 等于($pattern 之前的空白/制表符)后跟 # 加上任何内容(#pattern#whatever) [ \t]pattern#[^ \t]好的,和上面一样,只是散列而不是点。
  • 喜欢#whatever.pattern 或#whatever#pattern(#whatever 之前和#pattern 之后的空白/制表符)。 [ \t]#[^ \t].pattern[ \t]或者 [ \t]#[^ \t]#pattern[ \t]

没有。 2和3几乎一样。如果我们指的是 A 或 B,我们可以简单地组成一个组 [#.]。在组内,我们不需要屏蔽点,因为作为 clown 的点在组中没有任何意义。

没有。因此 2 和 3 合并为

[ \t]pattern[#.][^ \t][ \t]

但是!你不会用“随便”做任何事情。不管它是什么,它都没有改变。所以我们添加 # 和 .只是分隔符列表(空白和制表符)并返回它们(或空白或制表符),无论它们是什么:

[ \t]pattern([#. \t])

一个简单的测试:

echo "well #menu not #menu-false #menu.dot #menu#hash" \
| sed -r 's/[ \t]#menu([#. \t])/ #MENU\1/g' 
well #MENU not #menu-false #MENU.dot #MENU#hash

这将修改#Menu 前面的内容,无论是空白还是制表符,始终为空白。如果需要,我们也可以捕获它。

| sed -r 's/([ \t])#menu([#. \t])/\1#MENU\2/g' 

但是最后一条规则是什么,第 4 条,“whatever”领先于“pattern”?我们可以结合点和散列:

[ \t]#[^ \t][.#]menu[ \t]

将这种情况组合到我们的正则表达式中将允许#foo#pattern#bar。这变得越来越复杂了。我们最好开始一个全新的命令:

s/([ \t]#[^ \t]+[.#])menu[ \t]/\1MENU /g'

可以附加';'在上一个之后:

| sed -r 's/[ \t]#menu([#. \t])/ #MENU\1/g;s/([ \t]#[^ \t]+[.#])menu[ \t]/\1MENU /g'

所以我想我解决了您的 4 条规则,但顶部的示例只解决了其中的两条。你的尝试再次包括\<\>这只会令人困惑。

这是我自制的例子,包括规则 4 的情况:

echo "well #bar.menu and #foo#menu #menu not #menu-false #menu.dot #menu#hash" \
| sed -r 's/[ \t]#menu([#. \t])/ #MENU\1/g;s/([ \t]#[^ \t]+[#.])menu[ \t]/\1MENU /g'

well #bar.MENU and #foo#MENU #MENU not #menu-false #MENU.dot #MENU#hash

关于regex - 使 sed 仅替换精确的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6832705/

相关文章:

c# - 使用 Regex.Replace() 将 cm 转换为 mm

php - 双方括号内任何内容的正则表达式

linux - 从 shell 脚本调用 erlang 文件的函数

c - 将 C 变量的值赋给 bash 变量

regex - linux/unix 中的模式匹配或 RegEx 手册页?

python - Ubuntu 上的 "Daemon"- 登录失败

javascript - 字符串操作,在数字之前插入一个字符串

c++ - 使用 -Wpedantic : "style of line directive is a GCC extension" 编译 .cu 时出现警告

linux - 无法启动 php-fpm - "cannot get uid for user ' apache'”

JavaScript 正则表达式,替换除给定选择之外的所有字符。