Extract part of a string using bash / cut / split

I have a line like this:

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

I need to extract the username ( joebloggs ) from this line and save it in a variable.

The format of the string will always be the same, with the exception of joebloggs and domain.com so I mean that the string can be split twice using cut ?

The first division will be divided into : and we will store the first part in a variable to pass the second division function.

The second division will split into / and store the last word ( joebloggs ) in a variable

I know how to do this in php using arrays and partitions, but I'm a bit lost in bash.

+80
string bash
Oct 20 '13 at 19:56
source share
5 answers

To extract joebloggs from this line in bash using parameter extension without any additional processes ...

 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 

It joebloggs not depend on joebloggs whether joebloggs at a certain depth of the path.




Summary

An overview of several modes for expanding parameters, 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 

Thus, # means match from the beginning (think of a comment line), and % means from the end. One copy means the shortest, and two - the 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 specific lines or patterns using:

 ${MYVAR/search/replace} 

pattern has the same format as file name matching, so * (any characters) are common, often followed by a specific character, such as / or .

Examples:

Given a variable like

 MYVAR="users/joebloggs/domain.com" 

Delete the path, leaving the file name (all characters before the slash):

 echo ${MYVAR##*/} domain.com 

Delete the file name, leaving the path (delete the shortest match after the last / ):

 echo ${MYVAR%/*} users/joebloggs 

Get only the file extension (delete everything until the last period):

 echo ${MYVAR##*.} com 

NOTE. To perform two operations, you cannot combine them, but must be assigned to an intermediate variable. So, to get the file name without a path or extension:

 NAME=${MYVAR##*/} # remove part before last slash echo ${NAME%.*} # from the new var remove the part after the last period domain 
+235
Oct 20 '13 at 21:16
source share

Define a function like this:

 getUserName() { echo $1 | cut -d : -f 1 | xargs basename } 

And pass the line as a parameter:

 userName=$(getUserName "/var/cpanel/users/joebloggs:DNS9=domain.com") echo $userName 
+34
Oct. 20 '13 at 19:59
source share

What about sed? This will work in one command:

 sed 's#.*/\([^:]*\).*#\1#' <<<$string 
  • # are used for regular expression delimiters instead of / since it has / .
  • .*/ captures the string to the last backslash.
  • \( .. \) denotes a capture group. This is \([^:]*\) .
    • [^:] indicates any _ except for the colon, and * means zero or more.
  • .* means the rest of the line.
  • \1 means replacing what was found in the first (and only) capture group. This name.

Here's the breakdown corresponding to the regex string:

  /var/cpanel/users/ joebloggs :DNS9=domain.com joebloggs sed 's#.*/ \([^:]*\) .* #\1 #' 
+18
Dec 24 '14 at 20:54
source share

Using single sed

 echo "/var/cpanel/users/joebloggs:DNS9=domain.com" | sed 's/.*\/\(.*\):.*/\1/' 
+10
Oct. 20 '13 at 21:08
source share

Using one awk:

 ... | awk -F '[/:]' '{print $5}' 

That is, using a field separator like / or : username is always in field 5.

To save it in a variable:

 username=$(... | awk -F '[/:]' '{print $5}') 

More flexible implementation with sed , which does not require username to be field 5:

 ... | sed -es/:.*// -es?.*/?? 

That is, delete everything from : and beyond, and then delete everything to the last / . sed is probably faster than awk , so this alternative is definitely better.

+9
Oct 20 '13 at 20:08
source share



All Articles