bash string operation

Posted by jwright on Mon, 28 Feb 2022 02:55:52 +0100

Length of string

The syntax for obtaining the length of a string is as follows.

${#varname}

Here is an example.

$ myPath=/home/cam/book/long.file.name
$ echo ${#myPath}
29

Braces {} are required, otherwise Bash will interpret $# as the number of script parameters and variable names as text.

$ echo $#myvar
0myvar

In the above example, Bash explained $# and myvar separately.

Substring

The syntax of string extraction substring is as follows.

${varname:offset:length}

The meaning of the above syntax is to return the substring of the variable $varname, starting from the position offset (calculated from 0), and the length is length.

$ count=frogfootman
$ echo ${count:4:4}
foot

The above example returns the string frogfootman, which is a substring foot with a length of 4 starting from position 4.

This syntax can not directly manipulate the string. It can only read the string through variables and will not change the original string.

# report errors
$ echo ${"hello":2:3}

In the above example, "hello" is not a variable name, causing Bash to report an error.

If length is omitted, it starts from the position offset and returns to the end of the string.

$ count=frogfootman
$ echo ${count:4}
footman

The above example returns the substring of the variable count from position 4 to the end.

If offset is a negative value, it means it starts from the end of the string. Note that negative numbers must be preceded by a space to prevent confusion with the syntax for setting the default value of the variable of ${variable:-word}. At this time, you can also specify length, which can be positive or negative (negative value cannot exceed the length of offset).

$ foo="This string is long."
$ echo ${foo: -5}
long.
$ echo ${foo: -5:2}
lo
$ echo ${foo: -5:-2}
lon

In the above example, offset is - 5, which means that it is intercepted from the penultimate character, so long. Is returned. If the specified length is 2, lo is returned; If the length is - 2, it means to exclude 2 characters from the end of the string, so lon is returned.

Search and replace

Bash provides a variety of methods for string search and replacement.

(1) Pattern matching of string headers.

The following two grammars can check whether the beginning of a string matches a given pattern. If the matching is successful, delete the matching part and return the remaining part. The original variable will not change.

# If pattern matches the beginning of variable,
# Delete the part of the shortest match (non greedy match) and return the rest
${variable#pattern}

# If pattern matches the beginning of variable,
# Delete the longest match (greedy match) and return the rest
${variable##pattern}

The above two grammars will delete the matching part at the beginning of the variable string (replace it with null) and return the rest. The difference is that one is the shortest match (also known as non greedy match) and the other is the longest match (also known as greedy match).

Matching pattern can use * [] and other wildcards.

$ myPath=/home/cam/book/long.file.name

$ echo ${myPath#/*/}
cam/book/long.file.name

$ echo ${myPath##/*/}
long.file.name

In the above example, the matching pattern is / * /, where * can match any number of characters, so the shortest matching is / home /, and the longest matching is / home/cam/book /.

The following method can delete the directory part of the file path, leaving only the file name.

$ path=/home/cam/book/long.file.name

$ echo ${path##*/}
long.file.name

In the above example, the pattern * / matches the directory part, so only the file name is returned.

Let's take another example.

$ phone="555-456-1414"
$ echo ${phone#*-}
456-1414
$ echo ${phone##*-}
1414

If the match is unsuccessful, the original string is returned.

$ phone="555-456-1414"
$ echo ${phone#444}
555-456-1414

In the above example, pattern 444 cannot be matched in the original string, so it is returned as is.

If you want to replace the matching part of the head with other content, use the following writing method.

# The pattern must appear at the beginning of the string
${variable/#pattern/string}

# Examples
$ foo=JPG.JPG
$ echo ${foo/#JPG/jpg}
jpg.JPG

In the above example, the replaced JPG must appear at the beginning of the string, so JPG is returned JPG.

(2) Pattern matching at the end of the string.

The following two grammars can check whether the end of a string matches a given pattern. If the matching is successful, delete the matching part and return the remaining part. The original variable will not change.

# If pattern matches the end of variable,
# Delete the part of the shortest match (non greedy match) and return the rest
${variable%pattern}

# If pattern matches the end of variable,
# Delete the longest match (greedy match) and return the rest
${variable%%pattern}

The above two grammars will delete the matching part at the end of the variable string (replace it with null) and return the rest. The difference is that one is the shortest match (also known as non greedy match) and the other is the longest match (also known as greedy match).

$ path=/home/cam/book/long.file.name

$ echo ${path%.*}
/home/cam/book/long.file

$ echo ${path%%.*}
/home/cam/book/long

In the above example, the matching pattern is. *, Where * can match any number of characters, so the shortest match is Name, the longest match is file.name.

The following writing method can delete the file name part of the path, leaving only the directory part.

$ path=/home/cam/book/long.file.name

$ echo ${path%/*}
/home/cam/book

In the above example, the pattern / * matches the file name part, so only the directory part is returned.

The following writing method can replace the suffix of the file.

$ file=foo.png
$ echo ${file%.png}.jpg
foo.jpg

In the above example, the suffix of the file is changed from png changed to jpg.

Let's take another example.

$ phone="555-456-1414"
$ echo ${phone%-*}
555-456
$ echo ${phone%%-*}
555

If the match is unsuccessful, the original string is returned.

If you want to replace the matching part of the tail with other content, use the following writing method.

# The pattern must appear at the end of the string
${variable/%pattern/string}

# Examples
$ foo=JPG.JPG
$ echo ${foo/%JPG/jpg}
JPG.jpg

In the above example, the replaced JPG must appear at the end of the string, so JPG is returned jpg.

(3) Pattern matching at any position.

The following two syntax can check whether the string matches a given pattern. If the matching is successful, delete the matching part and return it with another string. The original variable will not change.

# If pattern matches part of the variable variable,
# The part of the longest match (greedy match) is replaced by a string, but only the first match is replaced
${variable/pattern/string}

# If pattern matches part of the variable variable,
# The part of the longest match (greedy match) is replaced by a string, and all matches are replaced
${variable//pattern/string}

The above two grammars are replacement under the longest match (greedy match). The difference is that the former grammar only replaces the first match, and the latter grammar replaces all matches.

$ path=/home/cam/foo/foo.name

$ echo ${path/foo/bar}
/home/cam/bar/foo.name

$ echo ${path//foo/bar}
/home/cam/bar/bar.name

In the above example, the former command only replaces the first foo, and the latter command replaces both foos.

The following example changes the separator from: to newline.

$ echo -e ${PATH//:/'\n'}
/usr/local/bin
/usr/bin
/bin
...

In the above example, the - e parameter of the echo command indicates that the character of the replaced string will be interpreted as a newline character.

Wildcards can be used in the pattern section.

$ phone="555-456-1414"
$ echo ${phone/5?4/-}
55-56-1414

In the above example, replace 5-4 with -.

If the string part is omitted, it is equivalent to replacing the matching part with an empty string, that is, deleting the matching part.

$ path=/home/cam/foo/foo.name

$ echo ${path/.*/}
/home/cam/foo/foo

In the above example, the string part after the second slash is omitted, so the pattern* Matching parts Return after name is deleted.

As mentioned earlier, there are two extensions to this syntax.

# The pattern must appear at the beginning of the string
${variable/#pattern/string}

# The pattern must appear at the end of the string
${variable/%pattern/string}

Change case

The following syntax can change the case of variables.

# Capitalize
${varname^^}

# Convert to lowercase
${varname,,}

Here is an example.

$ foo=heLLo
$ echo ${foo^^}
HELLO
$ echo ${foo,,}
hello

 

Transferred from:

String operation - Bash script tutorial - Network Channel

Topics: Linux bash