Learning_the_bash_Shell_Third_Edition 4.2/n(113|95)

Patterns and Pttern Matching

We’ll continue refining our solution to Task 4-1 later in this chapter. The next type of string operator is used to match portions of a variable’s string value against patterns. Patterns, as we saw in Chapter 1, are strings that can contain wildcard characters (*, ?, and [] for character sets and ranges). Table 4-2 lists bash’s pattern-matching operators.

Operator

Meaning

${variable#pattern}

If the pattern matches the beginning of the variable’s value, delete the shortest part that matches and return the rest.

${variable##pattern}

If the pattern matches the beginning of the variable’s value, delete the longest part that matches and return the rest.

${variable%pattern}

If the pattern matches the end of the variable’s value, delete the shortest part that matches and return the rest.

${variable%%pattern}

If the pattern matches the end of the variable’s value, delete the longest part that matches and return the rest.

${variable/pattern/string}

The longest match to pattern in variable is replaced by string. In the first form, only the first match is replaced. In the second form, all matches are replaced. If the pattern begins with a #, it must match at the start of the variable. If it begins with a%, it must match with the end of the variable. Ifstring is null, the matches are deleted. If variable is@or *, the operation is applied to each positional parameter in turn and the expansion is the resultant list

${variable//pattern/string}

The longest match to pattern in variable is replaced by string. In the first form, only the first match is replaced. In the second form, all matches are replaced. If the pattern begins with a #, it must match at the start of the variable. If it begins with a%, it must match with the end of the variable. Ifstring is null, the matches are deleted. If variable is@or *, the operation is applied to each positional parameter in turn and the expansion is the resultant list

These can be hard to remember; here’s a handy mnemonic device: # matches the front because number signs precede numbers; % matches the rear because percent signs follow numbers.The classic use for pattern-matching operators is in stripping off components of pathnames, such as directory prefixes and filename suffixes. With that in mind, here is an example that shows how all of the operators work. Assume that the variable path has the value /home/cam/book/long.file.name; then:

Expression

Results

${path##/*/}

    long.file.name

${path#/*/}

   cam/book/long.file.name

$path           

    /home/cam/book/long.file.name

${path%.*}   

    /home/cam/book/long.file

${path%%.*}

   /home/cam/book/long

The two patterns used here are /*/, which matches anything between two slashes,and .*, which matches a dot followed by anything.

The longest and shortest pattern-matching operators produce the same output unless they are used with the * wildcard operator. As an example, if filename had the value alicece, then both ${filename%ce} and ${filename%%ce} would produce the result alice. This is because ce is an exact match; for a match to occur, the string ce must appear on the end $filename. Both the short and long matches will then match the

last grouping of ce and delete it. If, however, we had used the * wildcard, then ${filename%ce*} would produce alice because it matches the shortest occurrence of ce followed by anything else. ${filename%%ce*} would return ali because it matches the longest occurrence of ce followed by anything else; in this case the first and second ce.

kernel_get_var() {
 local token="$1="
 local entry="$(cat /proc/cmdline)"
 local result=""

 while echo "${entry}" | grep -q "${token}" ; do
#If the pattern matches the beginning of the variable’s value, delete the shortest part that matches and return the rest.    entry="${entry#*${token}}"
#If the pattern matches the end of the variable’s value, delete the longest part that matches and return the rest.    result="${entry%%[ ,]*} ${result}"    entry="${entry#* }"  done  echo "${result}" }

  

 #examples

${variable#pattern}

If the pattern matches the beginning of the variable’s value, delete the shortest part that matches and return the rest.

cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1$ . 1.sh console=
entry before:aa bb console= ccc ddd eee fff ggg
entry: ccc ddd eee fff ggg
cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1$ . 1.sh ccc
entry before:aa bb console= ccc ddd eee fff ggg
entry: ddd eee fff ggg
cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1$ cat 1.sh 
entry="$(cat cline)"
echo "entry before:${entry}"
token=$1
echo  "entry:${entry#*${token}}"

  the content of cline is:

aa bb console= ccc ddd eee fff ggg

when $1 is set to:

console=

  the result is(If the pattern matches the beginning of the variable’s value, delete the shortest part that matches and return the rest.):

        delete the shortest, and return the rest.

ccc ddd eee fff ggg

  

${variable%%pattern} 

If the pattern matches the end of the variable’s value, delete the longest part that matches and return the rest.

. 1.sh console=
entry before:aa bb console= ccc ddd eee fff ggg
entry  after:aa bb console= ccc ddd eee fff ggg
cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ cat 1.sh 
entry="$(cat cline)"
echo "entry before:${entry}"
token=$1
echo  "entry  after:${entry%%*${token}}"
cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ cat cline 
aa bb console= ccc ddd eee fff ggg

#2此时我们的内容是以"console="结尾,所以只会处理结尾的,酱紫看起来 delete的所谓的longest 感觉就没有什么意义了, 奇怪。

cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ cat cline 
aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkkconsole=
cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ . 1.sh console=
entry before:aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkkconsole=
entry  after:aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk 

  #longest

同时通过实验来看, 它只会remove 掉最后一个pattern,更准确的说应该算是截取(cut), cut完最后一个pattern后原样返回剩余的部分

在echo 截取后的结果的时候再最后面加了一个“&” 来检查实际截取的效果

#”aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console=console=“

cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ cat cline 
aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console=console=
cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ . 1.sh console=
entry before:aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console=console=
entry  after:aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console=&
cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ cat 1.sh 
entry="$(cat cline)"
echo "entry before:${entry}"
token=$1
echo  "entry  after:${entry%%${token}}&"
  result: "aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console="
 

#”aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console=“

cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ cat cline 
aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console=
cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ . 1.sh console=
entry before:aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console=
entry  after:aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= &

  

result :”aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= “(空格还在)

#二”aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console=console=console=“

cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ cat cline 
aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console=console=console=
cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ cat 1.sh 
entry="$(cat cline)"
echo "entry before:${entry}"
token=$1
echo  "entry  after:${entry%%${token}*}&"
cornerli@cornerli2:~/chromiumos/factory_install/temp/aug22-1/example-2$ . 1.sh console=
entry before:aa bb hhhconsole= ccc ddd eee fff ggg iiiii jjjjj kkkkk console= console=console=console=
entry  after:aa bb hhh&

 after: "aa bb hhh&",      看来 ”*“ 的作用真的是超级巨大,匹配到了最靠近左侧的那个

 

 
原文地址:https://www.cnblogs.com/winditsway/p/15175324.html