如何从字符串前面“删除” /删除字符?


13

我有一个要操纵的字符串。字符串是H08W2345678我将如何操纵它,这样输出才是W2345678

同样,如果我想删除最后4个字符,H08W2345678以便得到H08W234该怎么做呢?


1
有很多方法可以操纵字符串。有使用的特定原因sed吗?
don_crissti 2015年

@don_crissti没有理由,除了缺乏经验。欢迎其他选择...
3kstc

@don_crissti,故事:从一个经过筛选的CSV文件中,我从一行中获取一个参数,H08W2345678并且需要将其处理为。W2345678将此值与其他基准一起放入发送的电子邮件中。您将通过cron进行电子邮件发送。
3kstc 2015年

@don_crissti awk。我创建了一个数组,然后修改了数组中的每个元素(所有方法都不同-即将以秒为单位的Epoch时滞更改为日期等)
3kstc 2015年

2
您可以使用awk做类似的事情:printf %s\\n "XX,H08W2345678,YY" | awk -F, '{print substr($2, 4); print substr($2, 1, length($2)-4)}'
don_crissti 2015年

Answers:


19

仅使用bash(或ksh93该语法来自或的位置zsh):

string="H08W2345678"

echo "${string:3}"
W2345678

echo "${string:0:-4}"
H08W234

有关字符串操作的更多信息,请参见Wooledge Wiki 。


这需要bash 4.2或更高版本。请参见《 Bash参考手册》的旧版本,第3.5.3节“ Shell参数扩展”此处的小鸡的答案以查看旧的约束条件(“ 长度必须等于或大于零的数字。”);…(续)
斯科特,

(续)…请参阅Bash更改(在Bash Hackers Wiki上)(向下滚动到本节的底部),或在Case Western Reserve University的Technology Infrastructure Services组织中查看bash新闻(搜索“添加到bash-4.2”然后向下滚动到“ q。”)以查看修订。... ... ... ...  "${string:0:${#string}-4}" 在bash 4.1版本的作品,只要长度$string至少为4
斯科特

PS这也会使诸如的字符串阻塞,在该字符串abc-e中,当您放下前三个字符时,您将留在原处-e(因为echo -e它没有执行您想要的操作)。
斯科特(Scott)

8
$ echo "H08W2345678" | sed 's/^.\{3\}//'
W2345678

sed 's/^.\{3\}//'将会找到前三个字符,^.\{3\}并替换为空白。此处^.将匹配字符串开头的任何字符(^指示字符串的开头),\{3\}并将与之前的模式精确匹配3次。因此,^.\{3\}将匹配前三个字符。

$ echo "H08W2345678" | sed 's/.\{4\}$//'
H08W234

同样,sed 's/.\{4\}$//'将最后四个字符替换为空白($指示字符串的结尾)。


1
能否请您解释一下's/^.\{3\}//',并's/.\{4\}$//'为我还在学习sed的,非常感谢
3kstc

@ 3kstc:请检查编辑
heemayl

1
对于仅几个字符,我会使用....\{3\}因为对我而言)而不是因为它更容易阅读:sed -e 's/^...//' -e 's/....$//' 或在带有alteration:的单个表达式中使用sed -r 's/^...|....$//g'。如果要删除的字符超过几个,那么我将使用/.\{17}\/表达式代替/.............../
约翰尼

如果字符串是-e或,这将表现不佳-n。当然,对于短于4个字符的字符串,“删除最后4个字符”的含义是不确定的,但是,如果有人想要对此进行修改以删除第一个或最后一个字符,则可能会崩溃。
斯科特(Scott)

2

如果您有一个文件,其中的每一行都是您要砍掉的11个字符(或其他任何字符)的字符串, sed则可以使用该工具。处理单个字符串很好,但是这太过分了。对于单个字符串,如果可以访问bash 4.2或更高版本,Jason的答案可能是最好的。但是, and 语法似乎对bash来说是唯一的(好吧,bash,ksh93,mksh和zsh)—我在《 Shell命令语言的开放组基础规范》中没有看到它们。如果您坚持使用不支持子字符串扩展(提取)的POSIX兼容外壳,则可以使用${parameter:offset}${parameter:offset:length}

$ printf "%s\n" "${string#???}"
W2345678

$ printf "%s\n" "${string%????}"
H08W234

使用printf而不是echo防止类似的字符串abc-e,其中,当您放下前三个字符时,剩下的-e (并echo -e没有做您想要的事情)。

而且,如果您根本不使用Bourne系列外壳程序(或者您使用的是古老的POSIX之前的系统),则这些程序仍然可以使用:

$ expr " $string" : ' ...\(.*\)'
W2345678

$ expr " $string" : ' \(.*\)....'
H08W234

额外的前导空格是为了避免与价值观的问题$string 是实际expr经营者(如+,  /,  indexmatch)或选项(如  ----help或  --version)。


@StéphaneChazelas:(1)感谢您让我想起了大约40年前我认识的一个陷阱,并以某种方式设法忘记了。(2)我一直习惯用X; 例如expr "X$string" : 'X...\(.*\)'。IMO,这更容易阅读和理解。这有什么问题吗,或者有什么理由喜欢空格?(3)今天,我了解到expr + "$string" : '...\(.*\)'现在可以使用了。我不记得40年前的情况;是否已被广泛使用以推荐安全?(4)您错过了有关jasonwryan答案的注释,也错过了关于heemayl答案的轻率选择。
斯科特(Scott)

AFAIK,expr +仅GNU(不适用于Solaris或FreeBSD AFAICS)。我使用space而不是x,因为某些expr实现不太可能使用以空格开头的运算符,而使用as x也是,而且因为使用col开头的整理元素的可能性要小于with的排序x。但是后来我意识到,expr " $a" "<" " $b"对于字符串比较来说,它可能不是一个好选择,因为某些实现最终会在$a/ $b看起来像数字时进行数值比较。也许expr "@@$a"...expr "x $a"更安全。
斯特凡Chazelas

0

带有:

string="H08W2345678"

匹配3个或4个字符似乎很简单(对于大多数shell):

$ printf '%s\t%s\n' "${string#???}" "${string%????}"
W2345678      H08W234

对于较旧的外壳(例如Bourne外壳),请使用:

$ string=H08W2345678

$ expr " ${string}" : " ...\(.*\)"
W2345678

$ expr " ${string}" : " \(.*\)...." '
H08W234

如果需要数字字符计数,请使用:

$ expr " ${string}" : " .\{3\}\(.*\)"
W2345678

$ expr " ${string}" : " \(.*\).\{4\}" '
H08W234

当然,这些正则表达式也可用于sed,awk和bash 3.0+:

$ echo "$string" | sed 's/^.\{3\}//'
W2345678

$ echo "$string" | sed 's/.\{4\}$//'
H08W234

$ echo "$string" | awk '{sub(/^.{3}/,"")}1'
W2345678

$ echo "$string" | awk '{sub(/.{4}$/,"")}1'
H08W234

$ r='^.{3}(.*)$'; [[ $a =~ $r ]] && echo "${BASH_REMATCH[1]}"
W2345678

$ r='^(.*).{4}$'; [[ $a =~ $r ]] && echo "${BASH_REMATCH[1]}"
H08W234

-1

如何从字符串前面“删除” /删除字符?

我有一个要操纵的字符串。字符串为H08W2345678,我将如何操作它,因此输出仅为W2345678?

echo "H08W2345678" | cut -c 4-

这只能回答一半的问题。
库萨兰达

我相信您的反对意见是不公平的。这一半回答了posix上搜索时遇到的问题,删除了第一个字符,并且此页面显示在搜索结果中。此外,此页面标题仅涵盖问题的恰好一半。当我找到我喜欢的解决方案时,我回来了并做出了贡献-我认为这份工作cut比本页上的其他任何事情都要优雅得多。
aexl
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.