给定一个字符串,如何删除第一个字符的运行? (SED)

时间:2016-10-23 17:41:51

标签: regex bash sed

我需要一个sed命令,它接受一个字符串并从头开始删除第一个字符的所有副本(但不是从字符串的其余部分删除)。

例如,AAABAC应该生成BAC,因为第一个字母是A,所以我们从头开始删除整个A的运行。

我最初的想法是:

data=$(echo $data | sed 's/^.\+\(.*\)/\1/')

但这不起作用(输出空字符串)。如果我用特定字符替换第一个.,它将只为该字符成功工作,但我无法正确地将它传到通配符。

我认为.匹配我想要的第一个字符,但+不记得我想要的字母,并继续接受每个字符,直到字符串结束,所以括号什么都没有,所以整个字符串都没有被替换。我怎样才能最初接受任何角色,然后“锁定”+的那个角色?

4 个答案:

答案 0 :(得分:7)

您可以使用:

$> s='AAABAC'
$> sed -E 's/^(.)\1*//' <<< "$s"

BAC
  • (.)将匹配第一个字符,并在第1组
  • 中捕获它
  • \1*将匹配0个或更多相同字符的实例

或者这是一种纯粹的BASH方式:

$> shopt -s extglob
$> echo "${s##+(${s:0:1})}"

BAC

${s:0:1}为我们提供了$s的第一个字符,##+(${s:0:1})从头开始删除了第一个字符的所有实例。

答案 1 :(得分:3)

针对可移植性提供关于现有答案的路线图

注意:可以从问题中使用的语法和接受的答案中推断出 GNU sed正被使用,但问题不在于:如此标记,可能会引起更广泛的兴趣。

  • anubhava's helpful answer适用于 GNU sed,但不适用于(更多)严格遵守POSIX的sed实施,例如在macOS上找到的实现

  • Benjamin W.'s helpful answer适用于 GNU grep,因为需要-P选项支持PCRE,其他grep实现,例如在macOS上找到的那个,不支持。

  • soronta's helpful answer适用于使用GNU正则表达式库(大多数Linux发行版)的平台,或者更一般地,适用于其ERE(扩展正则表达式)语法的平台支持反向引用,作为POSIX spec.

    非标准扩展
    • 请注意,=~,Bash的正则表达式匹配运算符,是行为依赖于平台的罕见Bash功能之一,因为使用了相应的平台&#39 ; s正则表达式库。

这里有一个符合POSIX标准的解决方案,应该适用于所有类似现代Unix的平台,因为它使用 BRE basic 正则表达式),POSIX 为其指定反向引用支持:

$ echo 'AAABAC' | sed 's/^\(.\)\1*//'
BAC

答案 2 :(得分:2)

如果你的grep理解Perl兼容的正则表达式,你可以用grep做到这一点:

$ grep -Po '^(.)\1*\K.*' <<< 'AABAC'
BAC

$ grep -Po '^(.)\1*\K.*' <<< 'ABAC'
BAC

-o仅保留匹配项,\K是一个可变长度的后视,从字符串开头删除尽可能多的相同字符。

答案 3 :(得分:2)

Bash还支持正则表达式:

$ m='(.)(\1+)(.+)'; [[ AAAAABAC =~ $m ]]; printf '%s' "${BASH_REMATCH[3]}"
BAC

适用于GNU ERE正则表达式系统库(因系统而异)。