使用普通bash中的regexp提取子字符串

and*_*rux 88 regex bash

我正在尝试使用bash从字符串中提取时间,而且我很难搞清楚它.

我的字符串是这样的:

US/Central - 10:26 PM (CST)
Run Code Online (Sandbox Code Playgroud)

我想提取10:26部分.

任何人都知道只有使用bash这样做的方法 - 不使用sed,awk等?

就像,在PHP中我会使用 - 不是最好的方式,但它的工作原理如下:

preg_match( ""(\d{2}\:\d{2}) PM \(CST\)"", "US/Central - 10:26 PM (CST)", $matches );
Run Code Online (Sandbox Code Playgroud)

感谢您的帮助,即使答案使用sed或awk

Gil*_*not 180

使用纯:

$ cat file.txt
US/Central - 10:26 PM (CST)
$ while read a b time x; do [[ $b == - ]] && echo $time; done < file.txt
Run Code Online (Sandbox Code Playgroud)

bash正则表达式的另一个解决方案:

$ [[ "US/Central - 10:26 PM (CST)" =~ -[[:space:]]*([0-9]{2}:[0-9]{2}) ]] &&
    echo ${BASH_REMATCH[1]}
Run Code Online (Sandbox Code Playgroud)

使用grep和查看高级正则表达式的另一种解决方案:

$ echo "US/Central - 10:26 PM (CST)" | grep -oP "\-\s+\K\d{2}:\d{2}"
Run Code Online (Sandbox Code Playgroud)

使用sed的另一个解决方案

$ echo "US/Central - 10:26 PM (CST)" |
    sed 's/.*\- *\([0-9]\{2\}:[0-9]\{2\}\).*/\1/'
Run Code Online (Sandbox Code Playgroud)

使用perl的另一个解决方案

$ echo "US/Central - 10:26 PM (CST)" |
    perl -lne 'print $& if /\-\s+\K\d{2}:\d{2}/'
Run Code Online (Sandbox Code Playgroud)

最后一个使用awk:

$ echo "US/Central - 10:26 PM (CST)" |
    awk '{for (i=0; i<=NF; i++){if ($i == "-"){print $(i+1);exit}}}'
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢“sed”版本,但想警告其他人“sed”不一定采用“+”修饰符。一种解决方法是使用“{1, }”修饰符来匹配一个或多个。 (2认同)

jgs*_*key 74

    echo "US/Central - 10:26 PM (CST)" | sed -n "s/^.*-\s*\(\S*\).*$/\1/p"

-n      suppress printing
s       substitute
^.*     anything at the beginning
-       up until the dash
\s*     any space characters (any whitespace character)
\(      start capture group
\S*     any non-space characters
\)      end capture group
.*$     anything at the end
\1      substitute 1st capture group for everything on line
p       print it
Run Code Online (Sandbox Code Playgroud)

  • 我觉得这让我成为了一个即时的sed大师.我可以调整的一个好选择比我不理解的九个好. (7认同)
  • 您能解释一下为什么先用-n禁止打印然后再用/ p再次请求打印吗?省略`-n`标志和省略`/ p`指令不是一样吗?谢谢。 (4认同)
  • 它在 macOS 上的 bash 和 zsh 中输出空行 (4认同)
  • 感谢您的详细解释,有助于避免将来出现“我如何正则表达式 XXXX”的帖子。 (2认同)
  • @VictorZamanian 来自[此处](http://www.grymoire.com/Unix/Sed.html#uh-9):“默认情况下,sed 打印每一行。如果进行替换,则打印新文本而不是旧的。如果您对 sed 使用可选参数“sed -n”,默认情况下它不会打印任何新行。...当使用“-n”选项时,“p”标志将导致打印修改后的行。” (2认同)

dou*_*own 24

快速'n脏,无正则表达,低稳健性斩波技术

string="US/Central - 10:26 PM (CST)"
etime="${string% [AP]M*}"
etime="${etime#* - }"
Run Code Online (Sandbox Code Playgroud)

  • 嗨,如果它包含对进一步文档的引用或围绕该技术的一些名称以便人们可以去研究更多,那么这将是10倍更有用.对于感兴趣的,这是bash字符串操作,你可以在这里找到更多细节:https://www.tldp.org/LDP/abs/html/string-manipulation.html (6认同)
  • 那太脏了,我很惭愧,我自己也没有想到.+1` | 阅读区域破折号时间apm区域`也工作 (4认同)

小智 6

如果你的字符串是

foo="US/Central - 10:26 PM (CST)"
Run Code Online (Sandbox Code Playgroud)

然后

echo "${foo}" | cut -d ' ' -f3
Run Code Online (Sandbox Code Playgroud)

会做这项工作。

  • 或 `cut -c14-18` 当然只有在字符位置不改变的情况下。如果时区固定,则不会发生这种情况。 (2认同)