用布尔变量记录状态

1. 题目考点

这道题主要考 4 个点:

  1. 正则表达式 re.findall()
  2. 字符串切割 split()
  3. 用布尔变量记录状态,比如 inside_block
  4. 审题时区分:看起来像颜色代码,不一定真的要输出

这题最容易错的地方是:#BED#Cab 这种虽然符合 HEX 颜色格式,但它们出现在 CSS 选择器位置,不是在 { } 里面,所以不能输出。


2. 审题

题目给你 N 行 CSS 代码,让你从上到下找出合法的 HEX 颜色代码。

合法 HEX 颜色代码满足:

以 # 开头
后面是 3 位或 6 位
每一位只能是 0-9、a-f、A-F

例如:

#FFF
#025
#F0A1FB

不合法的例子:

#ffffab      # 6 位以外,多了
#abcf        # 4 位
#12365erff   # 含有 r,而且整体太长

但本题还有一个 CSS 语境限制:只输出 CSS 属性值里的颜色代码,不输出选择器里的颜色代码。

例如:

#BED
{
    color: #FfFdF8;
}

这里:

#BED

是选择器,不输出。

#FfFdF8

{ } 里面,是属性值,输出。


3. 思路提示

这题不要一上来就只想“写一个正则”。应该分两层想:

第一层,先判断当前这一行是不是在 CSS 代码块 { } 里面。

第二层,只在 { } 里面的内容中,用正则找合法颜色代码。

所以我们需要一个变量:

inside_block = False

它表示“当前是否已经进入 CSS 的 { } 代码块”。

遇到 {,说明进入 CSS 块:

inside_block = True

遇到 },说明离开 CSS 块:

inside_block = False

然后,只在 inside_block == True 的时候查找颜色代码。


4. 完整设计思路

第一步:读取输入行数

第一行是 N,表示后面有多少行 CSS 代码。

n = int(input().strip())

这里可以理解为:

读取第一行输入,并转成整数

第二步:准备正则表达式

合法颜色是:

# + 3 位十六进制数字
或者
# + 6 位十六进制数字

可以写成:

pattern = r'#[0-9a-fA-F]{3}(?:[0-9a-fA-F]{3})?(?![A-Za-z0-9])'

分开看:

#                 必须以 # 开头
[0-9a-fA-F]{3}    先匹配 3 位合法字符
(?:...)?          后面可以再跟 3 位,也可以不跟
(?![A-Za-z0-9])   后面不能继续跟字母或数字

最后这个 (?![A-Za-z0-9]) 很重要。

它是为了防止这种情况:

#12365erff

如果没有限制,程序可能会错误地把前面的 #12365e 当成合法颜色。实际上它后面还连着 rff,所以整个东西不应该被截断匹配。


第三步:只查 CSS 块内部

CSS 的基本结构是:

Selector
{
    Property: Value;
}

所以我们只应该查 {} 中间的内容。

这就是为什么要这样写:

if "{" in line:
    inside_block = True
    search_area = line.split("{", 1)[1]

这句话的意思是:如果这一行出现了 {,说明从 { 后面开始才是 CSS 块内容。

例如:

line = "div { color: #fff; }"

执行:

line.split("{", 1)

结果是:

["div ", " color: #fff; }"]

[1] 表示取 { 后面的部分:

" color: #fff; }"

因为 { 前面的 div 是选择器,不应该查颜色。


然后还要处理 }

if "}" in search_area:
    search_area = search_area.split("}", 1)[0]
    inside_block = False

例如:

search_area = " color: #fff; }"

执行:

search_area.split("}", 1)

结果是:

[" color: #fff; ", ""]

[0] 表示取 } 前面的部分:

" color: #fff; "

因为 } 后面的内容已经离开 CSS 块,也不应该查。


第四步:为什么要先处理 {,再处理 }

顺序很关键。

假设有一行:

#main { color: #fff; }

这一行里面同时有选择器 #main 和颜色值 #fff

我们真正要查的是:

color: #fff;

所以必须先用 { 切掉前面的选择器:

search_area = line.split("{", 1)[1]

得到:

 color: #fff; }

然后再用 } 切掉后面的部分:

search_area = search_area.split("}", 1)[0]

得到:

 color: #fff;

最后只在这一小段里面查颜色,就不会把选择器 #main 错误输出。


5. 代码实现

import re

if __name__ == "__main__":
    n = int(input().strip())

    pattern = r'#[0-9a-fA-F]{3}(?:[0-9a-fA-F]{3})?(?![A-Za-z0-9])'

    inside_block = False

    for _ in range(n):
        line = input()
        search_area = ""

        # 如果这一行出现 {,说明从 { 后面开始进入 CSS 块
        if "{" in line:
            inside_block = True
            search_area = line.split("{", 1)[1]

        # 如果已经在 CSS 块里面,就检查整行
        elif inside_block:
            search_area = line

        # 如果搜索区域里出现 },说明只查 } 前面的内容
        if "}" in search_area:
            search_area = search_area.split("}", 1)[0]
            inside_block = False

        # 在真正的 CSS 块内容中查找合法 HEX 颜色
        colors = re.findall(pattern, search_area)

        for color in colors:
            print(color)

6. 运行演示

看样例中的一部分:

#BED
{
    color: #FfFdF8; background-color:#aef;
    font-size: 123px;
    background: -webkit-linear-gradient(top, #f9f9f9, #fff);
}

第一行:

#BED

这时还没有进入 { },所以:

inside_block = False

不查这一行,所以 #BED 不输出。

第二行:

{

遇到 {,进入 CSS 块:

inside_block = True

第三行:

color: #FfFdF8; background-color:#aef;

现在在 CSS 块里面,所以用正则查找,找到:

#FfFdF8
#aef

第四行:

font-size: 123px;

没有 HEX 颜色,不输出。

第五行:

background: -webkit-linear-gradient(top, #f9f9f9, #fff);

找到:

#f9f9f9
#fff

遇到 } 后,离开 CSS 块:

inside_block = False

所以最后输出类似:

#FfFdF8
#aef
#f9f9f9
#fff
#ABC
#fff

注意,样例里的:

#BED
#Cab

都不输出,因为它们是选择器,不是 CSS 属性值。


7. 方法总结

这一类题不要只盯着正则。正确做法是先问自己:

我要匹配的东西,是否有出现位置限制?

这道题的限制就是:

只匹配 CSS 块内部的颜色代码

所以解题顺序应该是:

先确定范围
再写正则
最后输出匹配结果

可以总结成一句话:

状态变量 inside_block 负责判断“能不能查”,正则 pattern 负责判断“是不是合法颜色”。

8. 练习

请你尝试判断下面这段 CSS 应该输出哪些 HEX 颜色代码。

8
#header
{
    color: #ABCDEF;
    border-color: #abcd;
    background: #123;
}
#footer
{
    color: #12g;
}

提示:

  1. #header#footer 是选择器,不输出。
  2. #ABCDEF 是 6 位合法 HEX。
  3. #abcd 是 4 位,不合法。
  4. #123 是 3 位合法 HEX。
  5. #12g 里面有 g,不合法。
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇