使用带有RegEx的SED将下划线放回数百个CSS文件的链接中

Luk*_*uke 2 css regex linux sed

我有几百个(超过700个)Web文件夹,每个都包含离散的CSS样式表.(如果你很好奇,那就是在线课程.)

最近有人决定链接应该强调.我知道很久以前W3C决定,但这是一所大学,他们喜欢重新决定事情.

我一直在尝试使用RegEx搜索更新所有CSS文件并替换.

迄今为止的主要障碍是:

  • 视窗.我不喜欢它,我没有使用它.像FART这样的命令行实用程序非常适合单行内容,但是编写更加自定义和强大的搜索功能对它来说太过分了.
  • 多行.CSS文件的结构通常如下:

    a, .surveypopup{
    text-decoration:none;
        cursor:pointer;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    这意味着选择器("{")之前的部分始终与好东西分开.我希望匹配所有修改"a"而没有事件的选择器(例如:悬停),并确保任何带有"text-decoration:none"的内容都变成"text-decoration:underline",而不会弄乱任何其他可能夹在其中的样式代码之间.

  • 不区分大小写.对于RegEx,这应该不是问题.这个CSS的作者可能有也可能没有他们的大写创意.

我目前正在使用的命令行是这样的:

find . -iname "*.css" | xargs sed -i "" "s|\(\ba\(,\|\.\|\s\|\b\)\[^\{\]\*\{\[^\}\]\*\)text-decoration\:none|a.\1text-decoration:underline;|g"
Run Code Online (Sandbox Code Playgroud)

哪个产生:

sed: 1: "s|\(\ba\(,\|\.\|\s\|\b\ ...": RE error: invalid repetition count(s)
Run Code Online (Sandbox Code Playgroud)

我想知道我的需要是否有理由编写一个bash脚本?如果需要修改,那么创建每个文件的备份会很好.这样的多个操作在脚本中会更容易......

无论哪种方式,我认为我遇到了问题,因为我不知道要为sed逃脱什么,以及什么不能逃脱.

请帮忙!

bee*_*jay 6

一次操作整个文件,您可以使用:

s/(\ba(?=(?:\.|,|\s|{|#)))([^}{]*?{[^}]*?text-decoration:\s*)none(\s?!important)?;/$1$2underline;/g
Run Code Online (Sandbox Code Playgroud)

更好的格式,这是:

s/                          # find and replace
    (                       # group 1
        \b                  # a word boundary
        a                   # followed by 'a'
        (?=                 # where the next character (positive lookahead)
            (?:             # (inside a non-capturing group)
              \.|,|\s|{|#   # is one of '.', ',', '{', '#' or whitespace
            ) 
        )
    )
    (                       # group 2
        [^}{]*?             # then non-greedily match anything up to a '{' or '}'
                            # if '}' is found, the next character will not match
                            # and therefore the whole regex will not match
        {                   # and find the '{'
        [^}]*?              # and then non-greedily match anything until we 
                            # find 'text-decoration', but don't keep matching
                            # when a '}' is found
        text-decoration:    # then find 'text-decoration'
        \s*                 # and optional whitespace
    )
    none                    # and 'none'
    (\s?!important)?        # and optional '!important'
    ;                       # and a ';'
/
    $1                      # replace by group 1
    $2                      # then group 2
    underline;              # then 'underline;'
/g
Run Code Online (Sandbox Code Playgroud)

示例文件:

$ cat test.css
a { text-decoration: none; }
b, a { text-decoration: none; }
b, a, u { text-decoration: none; }
b, a.cat, u { text-decoration: none; }
b, a.cat, u { text-decoration: none !important; }
b, a, u {
    text-decoration: none;
}
b, a, u {
    color: red;
    text-decoration: none;
}
b, a, u {
    color: red;
    text-decoration: none;
    padding: 10px;
}
Run Code Online (Sandbox Code Playgroud)

结果:

perl -0777 -p -e 's/(\ba(?=(?:\.|,|\s|{|#)))([^}{]*?{[^}]*?text-decoration:\s*)none(\s?!important)?;/$1$2underline;/g' test.css
a { text-decoration: underline; }
b, a { text-decoration: underline; }
b, a, u { text-decoration: underline; }
b, a.cat, u { text-decoration: underline; }
b, a.cat, u { text-decoration: underline; }
b, a, u {
    text-decoration: underline;
}
b, a, u {
    color: red;
    text-decoration: underline;
}
b, a, u {
    color: red;
    text-decoration: underline;
    padding: 10px;
}
Run Code Online (Sandbox Code Playgroud)

您可以使用perl的-i标志(不要忘记设置备份扩展名!)来就地操作文件.

显然有许多其他可能的CSS规则可以包括a; 例如html>adiv a b; 这个正则表达式找不到第一个,并且会找到第二个,但在两种情况下都会"错误".基本上,只有当您可以对要操作的文本做出强有力的假设时,才可以将正则表达式用于这些类型的任务.

更新添加}到规则的一部分以避免匹配,例如:

b { background-image: url('http://domain.com/this is a picture.jpg'); }
u { text-decoration: none; }
Run Code Online (Sandbox Code Playgroud)