如何在shell脚本中分割字符串

4

我以以下格式拥有数据库名称

username_databasename

现在我想把单独的数据库备份放在用户名目录中,例如:
/backups/username/backup

如何从该字符串中获取用户名

如果字符串不包含下划线(_),则备用应转到

/backups/others/backup
7个回答

6

您可以做:

username=others
if echo $name | grep '_'; then
 username=$(echo $name | cut -d'_' -f 1)
fi

1
谢谢。我还想要的是,如果没有 (_) 存在,则默认用户名为“others”。 - John

5

Jonathan Leffler提供了一个简洁明了的答案。

如果出于某些原因您不想使用sed,可以将$(echo | sed)替换为:

username="${fullname%_*}"

它执行相同的操作。


3
您可以使用以下变体:

您可以使用以下变体:

case $fullname in
(*_*) username=$(echo $fullname | sed 's/_.*//');;
(*)   username=others;;
esac
backupdir="/backups/$username/backup"

2
在bash中,您可以使用数组,如下所示:
str="a/bc/def"
IFS="/" arr=($str)
echo ${arr[0]}; # prints 'a'
echo ${arr[1]}; # prints 'bc'
echo ${arr[2]}; # prints 'def'

echo ${arr[@]}; # prints 'a bc def'

如果您想使用不同的“分隔符”拆分字符串,只需将IFS =“ /”行更改为该分隔符,例如

str="a,bc,def"
IFS="," arr=($str)

1

这里不需要使用cutgrepsedawk。只需使用bash的内置参数替换:

db_name=username_databasename

username=others
if [[ ${db_name} =~ '_' ]]; then
   username=${db_name%%_*} 
fi
backup_dir=/backups/${username}/backup

我更喜欢每个脚本只使用一种语言,并尽可能少地分叉 :-)


0

你可以使用 awk:

username = `echo $name | awk -F"_" '{print $1}'`

0

如果你只想使用 bash,而且不想调用任何可能会耗费大量时间的外部程序(这只有在你需要频繁执行时才很重要,也许在这里并不是这种情况):

pax> export x=a ; if [[ "${x%%_*}" != "${x}" ]]; then
...>    export bkpdir=/backups/${x%%_*}/backup
...> else
...>    export bkpdir=/backups/others/backup
...> fi
pax> echo "     ${bkpdir}"
     /backups/others/backup

pax> export x=a_b ; if [[ "${x%%_*}" != "${x}" ]]; then
...>    export bkpdir=/backups/${x%%_*}/backup
...> else
...>    export bkpdir=/backups/others/backup
...> fi
pax> echo "     ${bkpdir}"
     /backups/a/backup

if语句通过将修改后的字符串与原始字符串进行比较来检测是否有下划线。如果有下划线,它们将不同。

${x%%_*}提供了从删除最长的_*模式(换句话说,它删除从第一个下划线到末尾的所有内容)开始的字符串。


一个(稍微)简单一些的变体是:

export bkpdir=/backups/others/backup
if [[ "${x%%_*}" != "${x}" ]]; then
    export bkpdir=/backups/${x%%_*}/backup
fi

它是仅限于Bash的哪个方面?%%操作在POSIX中已定义。此外,您不需要在每个地方都加上“export”。实际上,我不明白为什么您要加上它,因为您没有进行任何外部程序调用。 - Roman Cheplyaka
我的意思是“仅使用Bash”,而不是调用grep或sed等外部程序。我并不是说它只能在Bash中工作。通常情况下,如果存在疑问,我会使用export,因为很少有比试图弄清楚为什么已启动的进程看不到环境变量更烦人的事情了。然而,我使用export与我的答案无关 - 它只是支持代码,以提供完整的工作示例。 - paxdiablo
哈哈,我觉得我需要学习很多东西才能理解你的回答。你能否给我一些教程来了解导出、%%等内容。我也不太懂seb和awk。有没有一些教程可以让我像你一样编写程序。虽然我已经通过简单的步骤得到了答案,但我喜欢事情完成的方式。 - John
@Mirage,快速教程,考虑到评论大小限制:1/设置变量并不意味着它可以在稍后启动的子进程中使用。为了做到这一点,您需要导出它。2/%%是bash的东西,最好购买OReilly bash书籍:http://oreilly.com/catalog/9780596009656,他们还有一本名为“sed & awk”的适度好的书。或者,您也可以像我一样在IT行业工作30年 :-) - paxdiablo
谢谢伙计,但我已经看到了经验确实很重要。 - John

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接