在普通bash中使用正则表达式提取子字符串
Posted
技术标签:
【中文标题】在普通bash中使用正则表达式提取子字符串【英文标题】:Extract substring using regexp in plain bash 【发布时间】:2012-11-02 14:52:58 【问题描述】:我正在尝试使用 bash 从字符串中提取时间,但我很难弄清楚。
我的字符串是这样的:
US/Central - 10:26 PM (CST)
我想提取10:26
部分。
任何人都知道只使用 bash 来执行此操作的方法 - 不使用 sed、awk 等?
就像,在 php 中我会使用 - 不是最好的方法,但它可以工作 - 类似:
preg_match( ""(\d2\:\d2) PM \(CST\)"", "US/Central - 10:26 PM (CST)", $matches );
感谢您的帮助,即使答案使用 sed 或 awk
【问题讨论】:
【参考方案1】:使用纯bash:
$ 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
和环视高级正则表达式的另一种解决方案:
$ echo "US/Central - 10:26 PM (CST)" | grep -oP "\-\s+\K\d2:\d2"
另一种使用 sed 的解决方案:
$ 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\d2:\d2/'
最后一个使用 awk :
$ echo "US/Central - 10:26 PM (CST)" |
awk 'for (i=0; i<=NF; i++)if ($i == "-")print $(i+1);exit'
【讨论】:
酷!我有没有机会在模式中也使用连字符“-”?因为该 grep 返回一些匹配项,而我只对具有连字符、空格和时间的匹配项感兴趣..... 我可能已经得到了 perl 解决方案,但这是一个很好的加分项。谢谢! 感谢您让我知道 \K “技巧”。 grep 加上 perl 语法真的很强大。 我喜欢sed
版本,但想警告其他人sed
不一定采用+
修饰符。一种解决方法是使用1,
修饰符来匹配一个或多个。【参考方案2】:
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
【讨论】:
我觉得这让我成为了一个即时的 sed 大师。我可以调整的一个好选择比我不理解的九个要好。 感谢您的详细解释,有助于避免将来出现“我如何正则表达式 XXXX”的帖子。 您能解释一下为什么您先用-n
禁止打印,然后再用/p
请求打印吗?省略-n
标志和省略/p
指令不是一样吗?谢谢。
很好的答案!感谢您的帮助:-)
@VictorZamanian from here: "默认情况下,sed 打印每一行。如果它进行替换,则打印新文本而不是旧文本。如果您使用 sed 的可选参数, “sed -n”,默认情况下不会打印任何新行。...当使用“-n”选项时,“p”标志将导致打印修改的行。”【参考方案3】:
Quick 'n dirty、无正则表达式、低鲁棒性的斩波技术
string="US/Central - 10:26 PM (CST)"
etime="$string% [AP]M*"
etime="$etime#* - "
【讨论】:
这太恶心了,我很惭愧我自己没有想到。 +1| read zone dash time apm zone
也可以
非常干净,避免调用外部程序。
嗨,如果它包含对进一步文档的引用或围绕该技术的一些名称的引用,那么这将是有用的 10 倍,以便人们可以进行更多研究。对于感兴趣的,这是 bash 字符串操作,您可以在此处找到更多详细信息:tldp.org/LDP/abs/html/string-manipulation.html【参考方案4】:
如果你的字符串是
foo="US/Central - 10:26 PM (CST)"
然后
echo "$foo" | cut -d ' ' -f3
会做的。
【讨论】:
或cut -c14-18
当然只有在字符位置不变的情况下。如果时区是固定的,这不应该发生。
向先生询问正则表达式而不是剪切【参考方案5】:
foo="美国/中部 - 晚上 10:26 (CST)"
回声 $foo |日期 +%H:%M
【讨论】:
您好 Jimbro,欢迎来到 ***!不幸的是,这不是问题的解决方案。请注意,OP 希望从字符串中提取日期,您的解决方案返回当前日期。以上是关于在普通bash中使用正则表达式提取子字符串的主要内容,如果未能解决你的问题,请参考以下文章