【问题标题】:Bash String Format Comparison with WildcardsBash 字符串格式与通配符的比较
【发布时间】:2021-11-10 03:06:19
【问题描述】:

我对 bash 脚本相当陌生,并且试图仅回显与特定格式匹配的行。到目前为止我有这个代码:

LINE=1
while read -r CURRENT_LINE
    do 
        if [[ $CURRENT_LINE == ??-?-??? ]]
        then
            echo "$LINE: $CURRENT_LINE"
        fi    
        ((LINE++))
done < "./new-1.txt"

文本文件的每一行都包含与以下格式匹配的数字序列:“12-3-456”,但也包含不同格式的序列,例如“123-89203-9420”或“123” -456-7890”。我不太明白为什么 while 循环中的 if 语句在与格式匹配的行上不会导致 True。我也尝试过使用 *,但使用它会得到不正确的结果。

这里是文本文件 new-1.txt 的内容。我希望脚本输出“第 1 行:11-1-111”,但它不输出任何内容。

11-1-111
222-22-2222
333-33-3333
444-444-4444
555-555-5555

【问题讨论】:

  • 不清楚你不明白什么。 ? 匹配单个字符,并且 pattern 隐式锚定在开头和结尾。所以??-?-??? 只匹配长度正好为 8 个字符的字符串,其中第 3 个和第 5 个字符必须是连字符。 (其他六个可以是任何字符。)
  • 如果你能提供new-1.txt的例子和你的预期结果会更清楚。我假设您的文件包含与 chepner cmets 在同一行中的连字符以外的其他单词。
  • 我已将文本文件的内容添加到帖子中,由于某种原因,它没有回显任何内容,即使第一行与脚本中 if 语句的格式匹配。会不会是换行符?
  • 感谢您的更新。你对换行符是正确的。如果文件包含CR LF 换行符,则脚本将失败。请尝试dos2unix 删除尾随的CR 字符或将if 语句更改为if [[ $CURRENT_LINE == ??-?-???$'\r' ]] 之类的内容。使用正则表达式(作为 jared_mamrot 的答案)也可以。
  • @tngoy :您的模式适用于11-1-111,但当然不适用于您发布的其他示例字符串。如果您从未得到真正的匹配,则意味着该变量包含的内容与您想象的不同。我建议您在测试之前使用xxd &lt;&lt;&lt;$CURRENT_LINE 打印变量的内容,然后检查输出。

标签: string bash comparison


【解决方案1】:

regex 的说法中,? 使字符或选择成为可选,即,一个字符/选择最多允许出现一次,但也允许出现零次。

但是,== 操作不是正则表达式匹配运算符。是=~

因此,将您的 if 子句更改为以下内容即可。

[[ $CURRENT_LINE =~ "^[0-9]{2}-[0-9]{1}-[0-9]{3}$" ]]

这里

  • ^ 指定正则表达式的开头,$ 指定结尾。所以我们有一个紧密耦合的模式来匹配
  • [0-9] 表示一个范围,这里是从零到九的任意数字。
  • {n} 要求前面的字符/选择应与 n 完全匹配的次数

注意:您也可以使用更详细的[[:digit:]] 而不是[0-9]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 2012-03-02
    • 2013-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多