Regex 用于匹配年份1之前的字符串的正则表达式

Regex 用于匹配年份1之前的字符串的正则表达式,regex,string,bash,sed,split,Regex,String,Bash,Sed,Split,我有包括年份号的目录名。我想将它们拆分为年份编号之前的变量: 输入: 年份并不总是在同一个地方,但它总是有4位数字 我一年四季都需要 对于输入: Holidays.ca.old.2017.bla.bla 输出: 企图 我的代码输出的是年份号,有时还有其他错误的数字 我在tcl中使用它,它非常适合我: set name_split [regsub {\.[0-9]{4}\y.*} $name ""] 我仍然需要它作为bash脚本,如何使用它 这在bash中实际上不起作用: name_split

我有包括年份号的目录名。我想将它们拆分为年份编号之前的变量:

输入: 年份并不总是在同一个地方,但它总是有4位数字

我一年四季都需要

对于输入:

Holidays.ca.old.2017.bla.bla
输出: 企图 我的代码输出的是年份号,有时还有其他错误的数字

我在tcl中使用它,它非常适合我:

set name_split [regsub {\.[0-9]{4}\y.*} $name ""]
我仍然需要它作为bash脚本,如何使用它

这在bash中实际上不起作用:

name_split=$(echo $name | {\.[0-9]{4}\y.*}

您可以使用
sed

name="Holidays.uS.2019.bla.bla"
name_split="$(sed 's/\.[0-9]\{4\}\>.*//' <<< $name)"
echo $name_split
echo "Holidays.ca.old.2017.bla.bla" | sed 's/^\(.*\)\.[0-9]\{4\}.*$/\1/';

Holidays.ca.old
#!/bin/bash
test_str="Holidays.ca.old.2017.bla.bla"
reg_ex='^(.*)\.([0-9]{4})' # Easy to read reg_ex vs sed reg_ex gibberish
if [[ $test_str =~ $reg_ex ]]
then
  echo "1: ${BASH_REMATCH[1]}"
  echo "2: ${BASH_REMATCH[2]}"
fi
这里的
sed
命令意味着:

  • s/
    -替换:
  • \。
    -一个点
  • [0-9]\{4\}
    -四位数字
  • \>
    -尾随词边界
  • *
    -字符串的其余部分

使用空字符串。

这里有一个使用
sed
的选项:

name="Holidays.uS.2019.bla.bla"
name_split="$(sed 's/\.[0-9]\{4\}\>.*//' <<< $name)"
echo $name_split
echo "Holidays.ca.old.2017.bla.bla" | sed 's/^\(.*\)\.[0-9]\{4\}.*$/\1/';

Holidays.ca.old
#!/bin/bash
test_str="Holidays.ca.old.2017.bla.bla"
reg_ex='^(.*)\.([0-9]{4})' # Easy to read reg_ex vs sed reg_ex gibberish
if [[ $test_str =~ $reg_ex ]]
then
  echo "1: ${BASH_REMATCH[1]}"
  echo "2: ${BASH_REMATCH[2]}"
fi
正则表达式只捕获到最后一个点之前的所有内容,后跟四位数年份,然后仅替换为捕获的数量:

(.*)        match and capture everything up until
\.[0-9]{4}  a literal dot, followed by a four digit year
.*          consume the remainder of the input

下面是另一种不使用sed的方法:

name="Holidays.uS.2019.bla.bla"
name_split="$(sed 's/\.[0-9]\{4\}\>.*//' <<< $name)"
echo $name_split
echo "Holidays.ca.old.2017.bla.bla" | sed 's/^\(.*\)\.[0-9]\{4\}.*$/\1/';

Holidays.ca.old
#!/bin/bash
test_str="Holidays.ca.old.2017.bla.bla"
reg_ex='^(.*)\.([0-9]{4})' # Easy to read reg_ex vs sed reg_ex gibberish
if [[ $test_str =~ $reg_ex ]]
then
  echo "1: ${BASH_REMATCH[1]}"
  echo "2: ${BASH_REMATCH[2]}"
fi
输出:

1:Holidays.ca.old

2:2017

您可以通过以下方式完成:


这将删除一个句点,后跟四位数字,然后删除字符串末尾的任何内容(通配符)。

您可以在
sed
命令中添加额外的边界,以确保安全并传递所需的字符:

代码 特殊字符 如果您不希望通过特殊字符,则安全:

图表 这个图表显示了它是如何工作的

演出 此代码段显示表达式的性能,重复次数为100万次

repeat=1000000;
开始=日期。现在();
对于(变量i=repeat;i>=0;i--){
var string=“Holidays.1.2.3.4.at.old.1999.bla.bla.bla.bla.bla”;
var regex=/^([A-z0-9\.]*)(\.[0-9]{4}.*)/g;
var match=string.replace(regex,“$1”);
}
end=Date.now()-start;

console.log(“YAAAY!\”+match+“\”是一个匹配注释,我下面的答案是我以前的Tcl解决方案的直接转换。
\y
\b
或(此处)
\>
。在一些SED中,这些可能无法工作,因此我添加了一个替代方案。酷大thx,我如何将年份设置为变量?大thx,Regards@MikeShiwa使用
year=“$(sed's/*\.\([0-9]\{4\}\)\>./\1/”通过图形进行图形解释非常有用,使事情易于理解。
Holidays.1.2.3.4.at.old