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

Cra*_*nds 103 string bash

我有一个像这样的字符串:

/var/cpanel/users/joebloggs:DNS9=domain.com
Run Code Online (Sandbox Code Playgroud)

我需要从这个字符串中提取用户名:joebloggs并将其存储在一个变量中

除了joebloggs和domain.com之外,字符串的格式总是相同的,所以我认为字符串可以使用"cut"拆分两次?

第一次拆分将使用以下方式拆分字符串:我们将第一部分存储在一个varibale中以传递给第二个拆分函数.

第二次拆分将使用/拆分字符串并将最后一个字(joebloggs)存储到变量中

我知道如何使用数组和拆分在PHP中执行此操作,但在bash中我有点迷失.

ber*_*roe 285

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

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
Run Code Online (Sandbox Code Playgroud)

不依赖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
Run Code Online (Sandbox Code Playgroud)

摘要

一些参数扩展模式的概述,供参考......

${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)
Run Code Online (Sandbox Code Playgroud)

所以%意味着从一开始就匹配(想想一条评论线)和pattern意味着从最后开始.一个实例意味着最短,两个实例意味着最长.

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

${MYVAR/search/replace}
Run Code Online (Sandbox Code Playgroud)

您还可以使用以下命令替换特定字符串或模式

MYVAR="users/joebloggs/domain.com" 
Run Code Online (Sandbox Code Playgroud)

*格式与文件名匹配的格式相同,因此/(任何字符)都很常见,通常后跟特定的符号,如./

例子:

给出一个变量之类的

echo ${MYVAR##*/}
domain.com
Run Code Online (Sandbox Code Playgroud)

删除保留文件名的路径(所有字符都为斜杠):

echo ${MYVAR%/*}
users/joebloggs
Run Code Online (Sandbox Code Playgroud)

删除文件名,保留路径(删除最后的最短匹配joebloggs):

echo ${MYVAR##*.}
com
Run Code Online (Sandbox Code Playgroud)

获取文件扩展名(在上一期之前删除所有内容):

NAME=${MYVAR##*/}      # remove part before last slash
echo ${NAME%.*}        # from the new var remove the part after the last period
domain
Run Code Online (Sandbox Code Playgroud)

注意:要执行两项操作,您不能将它们组合,但必须分配给中间变量.所以要获取没有路径或扩展名的文件名:

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
Run Code Online (Sandbox Code Playgroud)

  • @Fadi 您必须将通配符切换到冒号之前,并使用 `#` 而不是 `%`。如果你只想要最后一个冒号之后的部分,使用 `${MYVAR##*:}` 来获取第一个冒号之后的部分,使用 `${MYVAR#*:}` (3认同)
  • 甜的!它是在执行 shell 内完成的,因此比使用其他命令的要快得多。 (2认同)
  • 朋友,你不知道我多少次回到这个答案.谢谢! (2认同)
  • 仅供参考 `${MYVAR::3}` 表达式在 zsh 中不起作用。返回“zsh:预期右大括号”。`:3:5` 或只是 `:3` 都可以正常工作。 (2认同)

Ste*_*ppo 38

定义这样的函数:

getUserName() {
    echo $1 | cut -d : -f 1 | xargs basename
}
Run Code Online (Sandbox Code Playgroud)

并将字符串作为参数传递:

userName=$(getUserName "/var/cpanel/users/joebloggs:DNS9=domain.com")
echo $userName
Run Code Online (Sandbox Code Playgroud)

  • 这个答案帮助我实现了我来到这里的目的。没有公认的答案,这个答案让我投票赞成简单。 (2认同)

Dav*_* W. 18

那怎么样?这将在一个命令中工作:

sed 's#.*/\([^:]*\).*#\1#' <<<$string
Run Code Online (Sandbox Code Playgroud)
  • #被用于正则表达式的分隔,而不是/因为字符串有/它.
  • .*/ 将字符串抓取到最后一个反斜杠.
  • \( .. \)标志着一个捕获组.这是\([^:]*\).
    • [^:]说任何字符_除了冒号,*意味着零或更多.
  • .* 意味着剩下的线.
  • \1意味着替换第一个(也是唯一一个)捕获组中的内容.这就是名字.

以下是将字符串与正则表达式匹配的细分:

        /var/cpanel/users/           joebloggs  :DNS9=domain.com joebloggs
sed 's#.*/                          \([^:]*\)   .*              #\1       #'
Run Code Online (Sandbox Code Playgroud)


Yan*_*san 10

使用单一的sed

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


Sto*_*ica 9

使用单个Awk:

... | awk -F '[/:]' '{print $5}'
Run Code Online (Sandbox Code Playgroud)

也就是说,使用/或作为字段分隔符:,用户名始终在字段5中.

将其存储在变量中:

username=$(... | awk -F '[/:]' '{print $5}')
Run Code Online (Sandbox Code Playgroud)

使用它的更灵活的实现sed不要求用户名为字段5:

... | sed -e s/:.*// -e s?.*/??
Run Code Online (Sandbox Code Playgroud)

也就是说,删除所有内容:,然后删除所有内容,直到最后一次/.sed可能也比它快awk,所以这个替代方案肯定更好.