bash学习记录(五) bash中关于变量的更多的知识

字符串操作

bash支持很多关于字符串的操作,不过可惜的是,这些操作缺乏统一性,有一些是使用参数等,另外一些是通过内建命令expr命令来实现,这会导致不同的语法功能的重叠,会比较混乱,下面简单介绍一下使用参数和命令的实现字符串的操作。

  • 字符串长度(String Length)

    1. $(#string) 这里是和C语言中的strlen()是相同的。

    2. expr length $string 同样表示string串的长度。

      1
      2
      3
      4
      5
      6
      7
      #! /bin/bash
      string=abcdefgHIGKL
      #使用第一种方法$(#string)
      echo "string的长度是:${#string}"
      #使用第二种方法使用expr内建命令 优点简单易懂
      echo "string的长度是:`expr length $string`"
      `
  • 字符串从开头匹配子字串的长度

    方法如下:

    1
    2
    3
    stringZ=abcABC123ABCab 
    echo `expr match "$stringZ" 'abc[A-Z]*.2'`
    echo `expr $stringZ : 'abc[A-Z]*.2'`
  • 匹配到子串的位置 (index)

    1
    echo `expr index $stringZ 'abc[A-Z]*.2'`
  • 子字符串的截取

    1. ${string:position} 从positon位置截取字符串string。

    2. ${string:positong:length} 从positon位置截取字符串string,并且限定截取长度为length。

    3. expr substr $string $positon $length 意思同上。

    4. expr match $string ‘\(substring \)’ 这里的substring是正则表达式。

      1
      2
      3
      4
      5
      #截取字符串
      echo ${stringZ:5}
      echo ${stringZ:5:4}
      echo `expr substr $stringZ 5 4`
      echo `expr match $stringZ '\(abc[A-Z]*.2\)'`
  • 从字符串中移除子字符串

    1. ${string#substring} substring是子字符串。并且需要注意的是:该方法表示的是向后移除该子字符串最短匹配到的字符串。

    2. ${string##substring} 与上面的正好相反。该方法表示的是向后移除该字符串最长匹配到的字符串。

    3. ${string%substring} 该方法表示的是由后向前移除该子字符串最短匹配到的字符串。

    4. ${string%%substring} 该方法表示的是由后向前移除该字符串最长匹配到的字符串。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      echo "移除字符串"
      echo ${stringZ#a*b}
      echo ${stringZ##a*b}
      echo ${stringZ%a*c}
      echo ${stringZ%%a*c}
      #结果:
      #ABC123ABCabc
      #c
      #abcABC123ABC
      #
  • 子字符串替换

    1. ${string/substring/replacement} 替换第一个匹配到substring的字符串,替换为replacement。

    2. ${string//substring/replacement} 替换所有匹配到的字符。

    3. ${string/#substring/replacement} 替换由前向后匹配到的字符。

    4. ${string/%substring/replacement} 替换由后向前匹配到的字符。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      echo "---------字符串替换---------"
      echo ${stringZ/abc/xyz}
      echo ${stringZ//abc/xyz}
      echo ${stringZ/#abc/xyz}
      echo ${stringZ/%abc/xyz}
      #结果:
      #xyzABC123ABCabc
      #xyzABC123ABCxyz
      #xyzABC123ABCabc
      #abcABC123ABCxyz

使用awk操作字符串

现学先卖,三十分钟学会AWK,快速了解和应用awk。

基于以上,使用awk练习。

工作流分为大致三部分, read->excute->repeat,实现对文本的处理。

程序机构

  • BEGIN 语法:BEGIN {awk-commands} 是可以省略的部分块,主要作用是声明变量,初始化变量,

  • BODY块 :{commonds},是必须填写的部分,主要作用是处理文本,会对输入的每一行都执行body块中的命令,并且body是没有关键字的。

-END :END {commands},同BEGIN,是可以省略的部分

基础语法

  • awk命令行,可以通过执行awk [-option] files来实现对files文件的处理。 如 awk {print} mark.txt 这里就不具体举例了,开头的链接里讲的非常详细,这里只做简单的记录和查看。

  • 使用命令文件方式 awk -f command.awk marks.txt 使用-f参数,可以使用文件中的命令。

  • awk基本选项 : 这里不具体总结,linux环境下终端 man awk可以看到非常多的选项。

基本使用示例

  1. 基本打印文件内容

    1
    2
    3
    4
    5
    6
    $ awk '{print}' mark.txt 
    1) Amit Physics 80
    2) Rahul Maths 90
    3) Shyam Biology 87
    4) Kedar English 85
    5) Hari History 89
  2. 打印具体项内容

    1
    2
    3
    4
    5
    6
    $ awk '{print $1 "\t" $2 }' mark.txt
    1) Amit
    2) Rahul
    3) Shyam
    4) Kedar
    5) Hari
  3. 添加限定条件的打印内容

    1
    2
    3
    4
    5
    $ awk  '/a/  {print $1 "\t" $2 }' mark.txt
    2) Rahul
    3) Shyam
    4) Kedar
    5) Hari

    结果只显示匹配到a的行

  4. 打印匹配到的行数

    1
    2
    $ awk 'BEGIN{count=0} /a/ { count++} END{print count}' mark.txt
    4
  5. 打印字符数量超过16的行

    1
    2
    3
    $ awk 'length($0) > 18' marks.txt
    3) Shyam Biology 87
    4) Kedar English 85

NOTE:在这里的参数和bash中的参数类似。$0当前行,$1之后表示对应文件的行的列。

内建变量

AWK提供了很多内建变量提供使用,能够起到很大的作用。

标准awk变量

  • ARGC 命令行参数个数

    1
    2
    $ awk 'BEGIN{print "argument=",ARGC}' one two three
    argument= 4
  • ARGV 命令行参数数组 如 ARGV[1]=...

  • CONVFMT 数字的约定格式,默认值是%.6g

  • ENVIRON 环境变量

    1
    2
    $ awk 'BEGIN {print "User is",ENVIRON["USER"]}'
    User is nanyin
  • FILENAME 当前文件的名称

    1
    2
    $ awk 'END{print "this file name is", FILENAME}' mark.txt
    this file name is mark.txt
  • FS 分割符 默认是空格也可以使用-F设置分割符

  • NF 当前行的字段数目

    1
    2
    $ awk 'END{print NF}' mark.txt
    4
  • NR 行号

  • FNR 当前文件的行号

  • OFS 输出字段分隔符

  • ORS 输出行分割符

  • RLENGTH 表示match函数匹配字符床的长度

    1
    2
    $ awk 'BEGIN {if(match("One  Three","ree")) {print RLENGTH}}'
    3
  • RSTART 表示match函数第一次匹配到的位置

    1
    2
    $ awk 'BEGIN {if(match("One  Three","ree")) {print RSTART}}' 
    8

操作符

与C语言的操作符基本相同,如数字的一元二元三元操作等,字符串的链接,数组元素等

正则表达式

AWK对正则的处理非常强大,通常你一个小小的正则表达式能够处理很复杂的问题。关于正则,有时间整理一篇专门关于正则的文章。

数组

AWK支持关联数组,也就是说,不仅可以使用数字索引的数组,还可以使用字符串作为索引。删除数组元素使用delete语句

流程控制

流程控制if while for 与C相同

函数

查手册吧。。一次性看不完。。。。内建函数手册,这里有在这章比较重要的字符串函数。接下来就来看看有哪些函数比较重要。

AWK对字符串操作的函数

整理出awk对字符串的几个具体函数操作。

  1. asort(source,dest,how)

  2. asorti(source,dest,how)

    以上两个函数的how先不解释,前两个参数分别为source数组和排序方式,第二个可以不写,默认使用第一位的进行排位。

    1
    2
    3
    4
    awk 'BEGIN{a[0]="xiaohong";a[1]="aiaolan";asort(a);for(i=2;i>=0;i--) {print a[i]}}'
    xiaohong
    aiaolan
    `

    asorti()函数会将顺序替换到数组的value处如:

    1
    2
    3
    awk 'BEGIN{a[0]="xiaohong";a[1]="aiaolan";asorti(a);for(i=2;i>=0;i--) {print a[i]}}'
    1
    0
  3. gensub(regexp,replacement,how[,target]) 类似gsub和sub

    替换匹配到的正则regexp为replacement.如果how是g或者G(global的简写),则表示替换所有使用regexp匹配到的字符串,target是目标字符串

    如果使用regexp未匹配到,则返回原始target的值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 第一个
    echo a b c a d | gawk '{print gensub(/a/,"AA",2)}'
    a b c AA d
    # 第二个
    awk '
    BEGIN{
    a="abc def"
    b = gensub(/(.+) (.+)/,"\\2 \\1","g",a)
    print b
    }'
    def abc
  1. gsub(regexp,replacement[,target])

    gsub中的‘g’其实是表示的是global,寻找目标的匹配到从左最长的,不重叠的,找到并且替换掉。

    1
    { gsub(/Britain/, "United Kingdom"); print }

    返回的值为匹配到的次数

  2. index(in,find)

    寻找in串内符合find匹配到的字符的index位置

    1
    2
    3
    $ awk 'BEGIN{
    quote> print index("hello","lo")}'
    4
  3. length([string]) 顾名思义,不解释了

    1
    2
    $ awk 'BEGIN{print length("hello")}'
    5

    NOTE: If no argument is supplied, length() returns the length of $0.

  4. match(string,regexp,[,array])

    使用正则匹配字符串,返回匹配到的位置,若未匹配到返回0

  5. split(string,array[,fieldsep[,seps]])

    分割string字符串,使用array存放分割后产生的字符组,使用fieldsep组为分割符,seps存放每次分割产生的分割符。一个分割出来的存放到array[1]中,第二个存放到array[2]中,以此类推。如果分割符fieldsep不写,则默认分割符为空格。

    1
    2
    3
    4
    5
    $ awk 'BEGIN{print split("cul-de-sac",a,"-",seps);for(i=1;i<4;i++){print a[i]}}' 
    3
    cul
    de
    sac
  6. sprintf(format,expression1,..)

    是printf的功能,并且能够返回字符串

  7. strtonum (str)

    类似java的parseInt()函数,由String字符串转成数字

  8. sub(regexp,replacement[,target])

    最左最长匹配原则进行匹配,sub个gsub的作用相同,分割字符串,并进行替换

  9. substr(string,start[,end])

    分割字符串

  10. tolower(string) & toupper(string)

    大小写转换

关于awk的就总结到这了。。十分基础的总结。。推荐文档,清晰明了。下一篇打算先整理整理正则表达式。现在哪里都会用到正则,还是很有必要看看正则的。

-------------本文结束感谢您的阅读-------------

本文标题:bash学习记录(五) bash中关于变量的更多的知识

文章作者:NanYin

发布时间:2018年05月01日 - 17:05

最后更新:2019年08月12日 - 13:08

原始链接:https://nanyiniu.github.io/2018/05/02/2018-05-05-bash_05_%E6%93%8D%E4%BD%9C%E5%8F%98%E9%87%8F/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。