string 使用 bash/cut/split 提取字符串的一部分
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19482123/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
extract part of a string using bash/cut/split
提问by Craig Edmonds
I have a string like this:
我有一个这样的字符串:
/var/cpanel/users/joebloggs:DNS9=domain.com
I need to extract the username (joebloggs
) from this string and store it in a variable.
我需要joebloggs
从这个字符串中提取用户名 ( ) 并将其存储在一个变量中。
The format of the string will always be the same with exception of joebloggs
and domain.com
so I am thinking the string can be split twice using cut
?
字符串的格式将始终相同,除了等joebloggs
,domain.com
所以我认为字符串可以使用cut
?
The first split would split by :
and we would store the first part in a variable to pass to the second split function.
第一个拆分将被拆分:
,我们将第一部分存储在一个变量中以传递给第二个拆分函数。
The second split would split by /
and store the last word (joebloggs
) into a variable
第二次拆分将被拆分/
并将最后一个单词 ( joebloggs
)存储到一个变量中
I know how to do this in php using arrays and splits but I am a bit lost in bash.
我知道如何使用数组和拆分在 php 中执行此操作,但我在 bash 中有点迷失。
回答by beroe
To extract joebloggs
from this string in bash using parameter expansion without any extra processes...
要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
Doesn't depend on joebloggs
being at a particular depth in the path.
不依赖于joebloggs
处于路径中的特定深度。
Summary
概括
An overview of a few parameter expansion modes, for reference...
几种参数扩展方式的概述,供参考...
${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
So #
means match from the beginning (think of a comment line) and %
means from the end. One instance means shortest and two instances means longest.
所以#
意味着从头开始匹配(想想注释行)和%
从最后开始。一个实例表示最短,两个实例表示最长。
You can get substrings based on position using numbers:
您可以使用数字根据位置获取子字符串:
${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)
You can also replace particular strings or patterns using:
您还可以使用以下方法替换特定的字符串或模式:
${MYVAR/search/replace}
The pattern
is in the same format as file-name matching, so *
(any characters) is common, often followed by a particular symbol like /
or .
的pattern
是在相同的格式的文件名匹配,所以*
(任何字符)是常见的,经常随后像特定符号/
或.
Examples:
例子:
Given a variable like
给定一个变量,如
MYVAR="users/joebloggs/domain.com"
Remove the path leaving file name (all characters up to a slash):
删除留下文件名的路径(所有字符最多为斜杠):
echo ${MYVAR##*/}
domain.com
Remove the file name, leaving the path (delete shortest match after last /
):
删除文件名,保留路径(删除 last 之后的最短匹配项/
):
echo ${MYVAR%/*}
users/joebloggs
Get just the file extension (remove all before last period):
仅获取文件扩展名(删除上一期之前的所有内容):
echo ${MYVAR##*.}
com
NOTE:To do two operations, you can't combine them, but have to assign to an intermediate variable. So to get the file name without path or extension:
注意:要执行两个操作,您不能将它们组合起来,而必须分配给一个中间变量。所以要获取没有路径或扩展名的文件名:
NAME=${MYVAR##*/} # remove part before last slash
echo ${NAME%.*} # from the new var remove the part after the last period
domain
回答by Stefano Sanfilippo
Define a function like this:
定义一个这样的函数:
getUserName() {
echo | cut -d : -f 1 | xargs basename
}
And pass the string as a parameter:
并将字符串作为参数传递:
userName=$(getUserName "/var/cpanel/users/joebloggs:DNS9=domain.com")
echo $userName
回答by David W.
What about sed? That will work in a single command:
sed呢?这将在单个命令中工作:
sed 's#.*/\([^:]*\).*##' <<<$string
- The
#
are being used for regex dividers instead of/
since the string has/
in it. .*/
grabs the string up to the last backslash.\( .. \)
marks a capture group. This is\([^:]*\)
.- The
[^:]
says any character _except a colon, and the*
means zero or more.
- The
.*
means the rest of the line.\1
means substitute what was found in the first (and only) capture group. This is the name.
- 将
#
被用于正则表达式的分隔,而不是/
因为字符串有/
它。 .*/
抓取字符串直到最后一个反斜杠。\( .. \)
标记捕获组。这是\([^:]*\)
。- 该
[^:]
说_except冒号任何字符,并*
表示零以上。
- 该
.*
表示该行的其余部分。\1
意味着替换在第一个(也是唯一一个)捕获组中找到的内容。这就是名字。
Here's the breakdown matching the string with the regular expression:
这是将字符串与正则表达式匹配的细分:
/var/cpanel/users/ joebloggs :DNS9=domain.com joebloggs
sed 's#.*/ \([^:]*\) .* # #'
回答by Yann Moisan
Using a single sed
使用单个 sed
echo "/var/cpanel/users/joebloggs:DNS9=domain.com" | sed 's/.*\/\(.*\):.*//'
回答by janos
Using a single Awk:
使用单个 awk:
... | awk -F '[/:]' '{print }'
That is, using as field separator either /
or :
, the username is always in field 5.
也就是说,使用/
或作为字段分隔符:
,用户名始终在字段 5 中。
To store it in a variable:
要将其存储在变量中:
username=$(... | awk -F '[/:]' '{print }')
A more flexible implementation with sed
that doesn't require username to be field 5:
一个更灵活的实现sed
不需要用户名作为字段 5:
... | sed -e s/:.*// -e s?.*/??
That is, delete everything from :
and beyond, and then delete everything up until the last /
. sed
is probably faster too than awk
, so this alternative is definitely better.
也就是说,删除所有内容:
,然后删除所有内容,直到最后一个/
. sed
可能也比 快awk
,所以这个替代方案肯定更好。