2012-11-14 223 views
55

我想从使用bash的字符串中提取时间,而且我很难搞清楚它。使用正则表达式中的正则表达式提取子字符串

我的字符串是这样的:

US/Central - 10:26 PM (CST) 

我想提取10:26部分。

任何人都知道只有bash才能做到这一点 - 不使用sed,awk等?

一样,在PHP中我会使用 - 不是最好的方式,但它的作品 - 是这样的:

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

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

回答

132

使用纯

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

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

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

使用grep和环视先进的正则表达式的另一种解决方案:使用SED

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

另一种解决方案:

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

另一种解决方案用perl:

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

和最后一个使用awk:

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

酷!任何机会我也使用模式中的连字符“ - ”?因为该grep返回一些匹配,我只对有连字符然后是空格然后时间感兴趣。 – andrux

+0

相应地编辑 –

+0

增加了另一个解决方案 –

15

快速“N脏,正则表达式免费,低健壮性斩劈核技术

string="US/Central - 10:26 PM (CST)" 
etime="${string% [AP]M*}" 
etime="${etime#* - }" 
+2

这太脏了,我感到羞愧,我没有想到它自己。 +1'|阅读区域破折号时间apm区域的作品 – Orwellophile

+0

非常干净,并且避免了对外部程序的调用。 –

46
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 
+0

欢迎来到StackOverflow!对不起,我意外地将此标记为“不是答案”。不幸的是,没有办法摆脱这种风险,但是这个标志很快就会被主持人拒绝。 –

+0

感谢您的欢迎。不用担心“不答复”的标志。 – jgshawkey

+5

我觉得这个让我成为一个即时sed大师。我可以调整的一个好的选择比我不明白的要好。 – Noumenon