regex sed out string可能包含一个或多个数字的字符串中间

bq9c1y66  于 2023-06-30  发布在  其他
关注(0)|答案(5)|浏览(73)

我的字符串是:

  • “测试_ABC_1-JAN-2022.BCK-gz; 1”
  • “测试_ABC_2022年1月30日.BCK-gz; 1”

在bash中运行:echo "TESTING_ABC_1-JAN-2022.BCK-gz;1" | sed 's/.*\([0-9]\{1,2\}-[A-Z][A-Z][A-Z]-[0-9][0-9][0-9][0-9]\).*/\1/'返回2022年1月1日,结果良好。
当我奔跑时:echo "TESTING_ABC_30-JAN-2022.BCK-gz;1" | sed 's/.*\([0-9]\{1,2\}-[A-Z][A-Z][A-Z]-[0-9][0-9][0-9][0-9]\).*/\1/'我得到2022年1月0日,但我想要2022年1月30日。
从我把我的线传进去。我如何才能在一行中获得个位数或两位数的日期,如“30-JAN-2022”或“1-JAN-2022”

tez616oj

tez616oj1#

  • 第一个解决方案:* 使用您显示的示例,请尝试以下awk代码。简单地使用awkgsub函数来全局替换从值的开始到-的第二次出现,以及从点到值的最后一个NULL,并打印当前行的剩余值。
awk '{gsub(/^[^_]*_[^_]*_|\..*/,"")} 1' Input_file
  • 第二种解决方案:* 使用GNU grep,请尝试以下代码。使用-oP选项打印匹配值,并分别使用这些选项启用PCRE regex。在主程序中,使用.*?概念进行非贪婪匹配,并从值的开始匹配到_的第二次出现使用它2次,然后使用\K选项忘记所有匹配值。之后,匹配.发生之前的值以获得所需的输出。
grep -oP '^(.*?_){2}\K[^.]*' Input_file

***第三种解决方案:***使用GNU awk及其match函数,该函数使用数组概念从匹配的正则表达式的捕获组创建索引(键)。

awk 'match($0,/^[^_]*_[^_]*_([^.]*)/,arr){print arr[1]}' Input_file

***第四种解决方案:***使用sed-E选项启用ERE(扩展正则表达式),使用regex ^[^_]*_[^_]*_([^.]*).*创建1个且唯一的捕获组,其中包含所需的值,并使用替代函数将整个值替换为仅捕获的值。

sed -E 's/^[^_]*_[^_]*_([^.]*).*/\1/' Input_file
  • 第五种解决方案:* 使用GNU grep请尝试以下操作,感谢“第四只鸟”。
grep -oP '^(?:[^_]*_){2}\K[^.]*' Input_file
z9gpfhce

z9gpfhce2#

使用awk并避免任何正则表达式要容易得多:

cat file

TESTING_ABC_1-JAN-2022.BCK-gz;1
TESTING_ABC_30-JAN-2022.BCK-gz;1

awk -F '[_.]' '{print $3}' file

1-JAN-2022
30-JAN-2022

另一种选择是使用grep -Eo和一个有效的正则表达式来表示DD-MON-YYYY的日期:

grep -Eo '[0-9]{1,2}-[A-Z]{3}-[0-9]{4}' file

1-JAN-2022
30-JAN-2022
bqf10yzr

bqf10yzr3#

使用sed

$ echo "TESTING_ABC_1-JAN-2022.BCK-gz;1
> TESTING_ABC_30-JAN-2022.BCK-gz;1" | sed -E 's/[^0-9]*([^.]*).*/\1/'
1-JAN-2022
30-JAN-2022
vecaoik1

vecaoik14#

你的正则表达式的问题是贪婪的*量词:.*将匹配尽可能多的字符,同时仍然能够匹配输入的其余部分。在许多正则表达式实现中,可以通过添加?来更改*的贪婪性。因此,/.*?a/将匹配尽可能少的字符,直到找到a。不幸的是,sed本身并不支持改变贪婪。这里有两个选项:
如果你的字符串总是在日期之前有一个_,你可以简单地将_添加到.*部分:

$ sed -r 's/.*_([0-9]{1,2}-[A-Z]{3}-[0-9]{4}).*/\1/' <<< "TESTING_ABC_30-JAN-2022.BCK-gz;1"
30-JAN-2022

或者只是grep相关部分:

$ grep -Po '[0-9]{1,2}-[A-Z]{3}-[0-9]{4}' <<< "TESTING_ABC_30-JAN-2022.BCK-gz;1"
30-JAN-2022
46qrfjad

46qrfjad5#

如果你想以最随意的硬编码方式来做,试试:

echo 'TESTING_ABC_1-JAN-2022.BCK-gz;1
      TESTING_ABC_30-JAN-2022.BCK-gz;1' | 

{m,g}awk ++NF OFS= FS='.+_|[.].+$' 

gawk -F'.+_|[.].+$' '$_=$--NF' # only if u know for certain 
                               # there aren't empty lines in btwn
1-JAN-2022
30-JAN-2022

相关问题