2012-06-29 83 views

回答

23

没有理由使用外部工具,如sed为此; bash中能做到内部,using parameter expansion

如果要修剪后:的字符,例如:

$ str=foo_bar:baz 
$ echo "${str%%:*}" 
foo_bar 

中都可以贪婪和非贪婪的方式做到这一点:

$ str=foo_bar:baz:qux 
$ echo "${str%:*}" 
foo_bar:baz 
$ echo "${str%%:*}" 
foo_bar 

特别是如果你在一个紧密的循环中调用这个,启动一个新的sed进程,写入进程,读取它的输出并等待它退出(以获得它的PID)可能会造成很大的开销,处理内部的bash w没有。


现在 - 通常,想要做到这一点的时候,你可能真的什么是拆分变量进入领域,能更好地配合read完成。

举例来说,假设你是从/etc/passwd读线:

line=root:x:0:0:root:/root:/bin/bash 
IFS=: read -r name password_hashed uid gid fullname homedir shell _ <<<"$line" 
echo "$name" # will emit "root" 
echo "$shell" # will emit "/bin/bash" 

即使要处理从一个文件中多条线路,这也可以使用bash单独做,没有外部进程:

while read -r; do 
    echo "${REPLY%%:*}" 
done <file 

...将从file每一行发出一切直至第一:,而不需要任何分机ernal工具将被发射。

8

什么你要找的其实是很容易的:

sed 's/A.*//' 

A标志着特定的字符。请注意,它是区分大小写的,如果你想捕获多个字符使用

sed 's/[aAbB].*//' 
2

如果文本包含文本,如

TEXT=beforexafter 

和特定的字符发生(例如)是x,然后

echo "${TEXT%x*}" 

你想要做什么。

来砸,"$TEXT""${TEXT}"是整个beforexafter,但"${TEXT%xafter}"只是before,与xafter砍掉结束。要砍掉x及其后的任何东西,可以写"${TEXT%x*}"。顺便说一句,还有"${TEXT%%x*}"。只有当有多个x时,才会有所不同。随着%%,Bash砍掉所有x,而与%它只从最后x砍掉。你可以通过松散地观察到更长的%%剔除更多文本。

你可以用桑达也这样做,当然,如果你喜欢:

echo "$TEXT" | sed 's/x.*//' 
+2

请把周围扩展报价 - '回声$ TEXT'会做字符串分割,因此,如果'TEXT'包含'$ 'foo \ t \ tbar \ nbaz'',它会简单地作为'foo bar baz'出现,而'echo'$ TEXT“'不会出现这个缺陷。 (永久使用全大写非环境变量的东西也是有点不幸;最好的做法是让它们小写以避免与环境变量和内建命名空间冲突)。 –

+0

@CharlesDuffy:你对引语是正确的:忽略它们是我的一个坏习惯,我应该从现在开始改革。关于全部大写,你提出了一个有趣的观点,更有趣的解释。我怀疑你对帽子的建议是好的。 – thb

+1

不是问题,而是相关的。在''之后运行'echo'$ {TEXT#* x}“'' –

相关问题