String 使用bash/cut/split提取字符串的一部分

String 使用bash/cut/split提取字符串的一部分,string,bash,String,Bash,我有这样一个字符串: /var/cpanel/users/joebloggs:DNS9=domain.com 我需要从这个字符串中提取用户名(joebloggs),并将其存储在一个变量中 字符串的格式将始终相同,但joebloggs和domain.com除外,因此我认为可以使用cut将字符串拆分两次 第一次拆分将被:拆分,我们将第一部分存储在一个变量中,以传递给第二次拆分函数 第二次拆分将被/拆分,并将最后一个单词(joebloggs)存储到一个变量中 我知道如何在php中使用数组和拆分来实现

我有这样一个字符串:

/var/cpanel/users/joebloggs:DNS9=domain.com
我需要从这个字符串中提取用户名(
joebloggs
),并将其存储在一个变量中

字符串的格式将始终相同,但
joebloggs
domain.com
除外,因此我认为可以使用
cut
将字符串拆分两次

第一次拆分将被
拆分,我们将第一部分存储在一个变量中,以传递给第二次拆分函数

第二次拆分将被
/
拆分,并将最后一个单词(
joebloggs
)存储到一个变量中


我知道如何在php中使用数组和拆分来实现这一点,但在bash中我有点迷失了方向。

定义如下函数:

getUserName() {
    echo $1 | cut -d : -f 1 | xargs basename
}
并将字符串作为参数传递:

userName=$(getUserName "/var/cpanel/users/joebloggs:DNS9=domain.com")
echo $userName
使用单个Awk:

... | awk -F '[/:]' '{print $5}'
也就是说,使用
/
作为字段分隔符时,用户名始终位于字段5中

要将其存储在变量中,请执行以下操作:

username=$(... | awk -F '[/:]' '{print $5}')
使用
sed
实现更灵活,不需要用户名作为字段5:

... | sed -e s/:.*// -e s?.*/??
也就是说,删除
及其后的所有内容,然后删除直到最后一个
/
为止的所有内容
sed
可能也比
awk
快,所以这个替代方案肯定更好。

使用单个sed

echo "/var/cpanel/users/joebloggs:DNS9=domain.com" | sed 's/.*\/\(.*\):.*/\1/'

要在bash中使用参数扩展从该字符串中提取
joebloggs
,无需任何额外的进程

MYVAR="/var/cpanel/users/joebloggs:DNS9=domain.com" 

NAME=${MYVAR%:*}  # retain the part before the colon
NAME=${NAME##*/}  # retain the part after the last slash
echo $NAME
不依赖于
joebloggs
位于路径中的特定深度


摘要

几个参数展开模式的概述,供参考

${MYVAR#pattern}     # delete shortest match of pattern from the beginning
${MYVAR##pattern}    # delete longest match of pattern from the beginning
${MYVAR%pattern}     # delete shortest match of pattern from the end
${MYVAR%%pattern}    # delete longest match of pattern from the end
因此,
#
表示从头开始匹配(想想注释行),而
%
表示从头开始匹配。一个实例表示最短,两个实例表示最长

可以使用数字根据位置获取子字符串:

${MYVAR:3}   # Remove the first three chars (leaving 4..end)
${MYVAR::3}  # Return the first three characters
${MYVAR:3:5} # The next five characters after removing the first 3 (chars 4-9)
还可以使用以下方法替换特定字符串或模式:

${MYVAR/search/replace}
模式
的格式与文件名匹配的格式相同,因此
*
(任何字符)都很常见,后面通常跟一个特定的符号,如
/

示例:

给定一个变量,如

MYVAR="users/joebloggs/domain.com" 
删除留下文件名的路径(所有字符最多为斜杠):

删除文件名,保留路径(删除最后一个
/
之后的最短匹配):

仅获取文件扩展名(删除上一期间之前的所有文件):

注意:要执行两个操作,不能将它们合并,但必须指定给中间变量。因此,要获取不带路径或扩展名的文件名:

NAME=${MYVAR##*/}      # remove part before last slash
echo ${NAME%.*}        # from the new var remove the part after the last period
domain

赛德呢?这将在单个命令中工作:

sed 's#.*/\([^:]*\).*#\1#' <<<$string

我不确定这是支持还是反对创造性地使用grep,但请使用VAR=/here/is/a/path:with/a/colon/inside:DNS9=domain.comSweet试试!而且它是在执行shell中完成的,因此比使用其他命令快得多。@Fadi您必须切换通配符,使其位于冒号之前,并使用
而不是
%
。如果您只想要最后一个冒号后面的部分,请使用
${MYVAR##*:}
获取第一个冒号后面的部分,使用
${MYVAR#*:}
朋友,您不知道我有多少次回到这个答案。非常感谢。回答得好!问题:如果我的模式是一个变量,我会像这样键入
${RET##*$CHOP}
还是像这样键入
${RET##*CHOP}
(或其他方式)?编辑:似乎是前者,
${RET##*$CHOP}
这个答案帮助我实现了我来这里的目的。没有一个被接受的答案,这一个因为简单而得到我的投票。我在上面的命令中所做的唯一更正是删除“:”,就像这样
echo$1 | cut-d-f1 | xargs
+请描述答案的
cut-d:-f 1 | xargs basename
部分,以便对其他具有类似用例的人有用。请仔细分析!
echo ${MYVAR##*.}
com
NAME=${MYVAR##*/}      # remove part before last slash
echo ${NAME%.*}        # from the new var remove the part after the last period
domain
sed 's#.*/\([^:]*\).*#\1#' <<<$string
        /var/cpanel/users/           joebloggs  :DNS9=domain.com joebloggs
sed 's#.*/                          \([^:]*\)   .*              #\1       #'