【问题标题】:Bash extract substring from a generic stringBash 从通用字符串中提取子字符串
【发布时间】:2023-03-17 13:15:02
【问题描述】:

我有字符串,例如

username/ticket-12345/feature

我只想提取

ticket-12345

来自 bash。这个字符串的格式可以是任何东西......例如

'my string ticket-12345'

和'ticket'可以是小写和大写的混合。 这可以从bash中做到吗?我试过搜索这个特殊情况,但我似乎找不到答案......

【问题讨论】:

    标签: string bash substring


    【解决方案1】:

    带有-o 标志的grep 及其朋友只显示找到的匹配项。你可以使用

    egrep -io 'ticket-[0-9]+' file.txt
    

    从您输入的文本中查找票证。

    【讨论】:

    • 点头。工作(在大多数平台上,-o being a non-POSIX extension),更新后——这是否比纯 bash 方法更合适取决于使用上下文(grep 可以更快地扫描大文件,但如果每个调用都在评估只有一行,那么由于forkexec() 外部进程所需的开销,它会比shell-builtin 替代方案慢得多。
    • @CharlesDuffy:没错,我会记住它和你的解决方案。
    【解决方案2】:

    shell 的内置 ERE(扩展正则表达式)支持足以完成任务:

    ticket_re='[Tt][Ii][Cc][Kk][Ee][Tt]-[[:digit:]]+'
    string='my string ticket-12345'
    
    [[ $string =~ $ticket_re ]] && echo "Found ticket: ${BASH_REMATCH[0]}"
    

    【讨论】:

    • 您也可以使用nocasematchticket-[[:digit:]]+ 来忽略“ticket”的大小写,但如果您需要将其范围限制为仅这一匹配,这会变得很尴尬。
    【解决方案3】:

    这是一个纯 bash 正则表达式方法:

    re='[[:alpha:]]+-[0-9]+'
    
    s='username/ticket-12345/feature'
    [[ $s =~ $re ]] && echo "${BASH_REMATCH[0]}"
    ticket-12345
    
    s='my string ticket-12345'
    [[ $s =~ $re ]] && echo "${BASH_REMATCH[0]}"
    ticket-12345
    

    【讨论】:

    • 嗯。我可能提前 15 秒点击了“发布”,但我认为你的答案更强;我们的方法之间唯一的功能区别是ticket 可以是任何字母字符串,还是只能由字母T/tI/iC/c、@987654329 组成@/k,等等
    • ...也就是说,最好从[A-Za-z] 更改为[[:alpha:]],因为A-Z 方法是排序顺序/区域设置相关的。
    • 是的,没错,如果 OP 在混合情况下只想要 ticket,那么这个正则表达式可能太通用了。
    • 在撰写本文时,我实际上并不需要泛型方法,但这是完美的。谢谢!
    猜你喜欢
    • 2012-09-24
    • 2011-07-21
    • 1970-01-01
    • 2021-10-31
    • 2015-04-26
    相关资源
    最近更新 更多