• bash5----进阶2 操作字符串


    1、命令expr  : evaluate expressions(支持模式匹配和字符串操作。字符串表达式的优先级高于数值表达式和逻辑关系表达式。)

      SYNOPISIS

        expr EXPRESSITONS

        expr OPTION

      expr ARG1 {+ - * / | & < <= > >= != %} ARG2 

      expr STRIGN : REGEXP == expr match "STRING" 'REGEXP'  (如果成功返回匹配到的字数,也可以用于计算字符串长度)

      substr STRING POS(postion) LENGTH  (提取子串见2)

      index STRING CHARS    #类似于C里面的strchr,当见到第一个字符,即返回字节数

      length STRING   (字符串长度见下文)

      + TOKEN:将TOKEN解析为普通字符串,即使TOKEN是像MATCH或操作符"/"一样的关键字。这使得'expr length + "$x"'或'expr + "$x" : '.*/(.)''可以正常被测试,即使"$x"的值可能是'/'或'index'关键字。这个操作符是一个GUN扩展。

    更多的详细内容可以看大佬博文

    字符串长度:法1:echo `expr length $Stringname`

          法2:echo ${#Stringname}

          法3:echo `expr "$Stringname" : '.*'`  ==  expr "$Stringname" : '.*'

    抄个例子,在一个文本文件的段落之间插入空行

     #!/bin/bash
     # paragraph-space.sh
    
     # 在一个单倍行距的文本文件中插入空行.
     # Usage: $0 <FILENAME
    
     MINLEN=45 # 可能需要修改这个值.
     # 假定行的长度小于$MINLEN所指定的长度的时候
     #+ 才认为此段结束.
    
     while read line # 提供和输入文件一样多的行...
     do
     echo "$line" # 输入所读入的行本身.
    
     len=${#line}
     if [ "$len" -lt "$MINLEN" ]
     then echo # 在短行(译者注: 也就是小于$MINLEN个字符的行)后面添加一个空行.
     fi
     done
    
     exit 0
    

      这个是书本上的例子,很显然不能直接执行,不过给我们提供了一个思路。如何给段落(长度小于45的段落)中间添加空行

    首先还是需要明白read这个函数的用法:

    首先 shell里面的read 和函数read还是不一样的,一个是从stdio中读取,一个是高级编程中常用的函数。我们通常使用man read 的这个read看到的是unistd.h里面的read函数。如果想看到shell中read的用法 通常使用read --help(我姑且这么认为,有问题欢迎大家评论批评)。

    那么"read --help"是这么描述的:

      read: read [-ers] [-a array] [-d delim] [-i text] [-n nchar] [-p prompt] [-t timeout] [-u fd] [name ...]

      :-a 后面参数是数组。-d 分隔符换成 delim,并根据 'delim'来分行 而不是回车。-n后面接数字,定义输入文本长度。-p 后面接PROMPT作为输出提示信息。 -t 后面接秒数,代表等待时间。-u 从fd中读入。

        Read a line from the standard input and split it into fields.

    上面是把stdin在command line 用 '<' 重定向到FILENAME中,然后用echo来输出到stdout里面。

    下面有几种变化方式,来将他变形一下:

      1、可以把上面第11行while read line 改成 cat FILENAME(也可以用绝对路径) | while read line 。这样就不用再命令行输入bash Scription.sh < FILENAME

      2、如果想把结果输出到FILENAME2中,则可以在命令行输入 bash Scription.sh <FILENAME1 >FILENAME2

      3、同样也吧上面第19行改成: done >FILENAME2

      4、还可以使用文件描述符来表示,[i]<>filename打开文件filename来读写,并且分配文件描述符i给这个文件。如果filename不存在,则他会被创建,然后 read -u fd ARG

    2、提取子串,子串削除,子串替换

    ${string:position} :在位置$position开始提取子串,长度为$length(长度可以加在position后面也可不加)。

    2.1、如果$string 是“*”或“@”,那么将会提取从$position开始的位置参数

    2.2、string提取的时候是0-based indexing

    2.3、position为负数时候,是倒数,但是需要加括号表示,

    EG:

    stringZ=abcABC123ABCabc

    echo ${stringZ:0}  #abcABC123ABCabc

    echo ${stringZ:7:3}  #23A

    echo ${stringZ:(-4)}  #Cabc。倒数第4个开始? 注意加括号转义,如果不加 可能为${stringZ:-default}一样了

    echo ${*:2}  #打印第二个以及后面的参数

    expr substr $string $position $length

    EG:  echo `expr substr $stringZ 1 2`  #12

    expr match "$string" '($substring)'  == expr "$string" : '($substring)'  都是提取子串

    不同于返回子串长度  expr match "$string" '$substring'  == expr "$string" : '$substring'  ,少了两个转义的小括号。加不加echo 效果也一样。

    从结尾提取substring:

    expr match "$string" '.*($substring)'  == expr "$string" : '.*($substring)'    [多了"  .*   " 在小括号前]

    子串削除

    ${string#substring}从string 的开始位置截掉最短匹配的$substring

    ${string##substring}从string的开头位置开始截掉最长的$substring

    ${string%substring}从结尾开始截掉最短

    ${string%%substring}从结尾开始截掉最长

    子串替换

    ${string/substring/replacement}使用$replacement来替换第一个匹配的$substring

    ${string//substring/replaement}使用$replacement来替换所有匹配的$substring

    ${string/#substring/replaement}如果$replacement匹配开头部分,则使用$replacement来替换匹配的$substring

    ${string/%substring/replaement}如果$replacement匹配结尾部分,则使用$replacement来替换匹配的$substring

    图像转换:

    1、关于Netpbm

    Netpbm是一个很好用的,很强大的命令方式图像处理程序,(先将png转换成pnm格式,再将pnm转换成bmp.pnm是LINUX下的一种原始图像存储格式,类似于WINDOWS下的BMP).特别适合图像批量处理,尤其是在LINUX下与SHELL配合。

     关于netpbm的相关programs可以在这个网站查找:http://www.linuxguruz.com/man-pages/?topic=pnm

     jpg全名是JPEG [   Joint Photo graphic Experts Group ] 。JPEG图片以 24 位颜色存储单个位图。JPEG 是与平台无关的格式,支持最高级别的压缩,不过,这种压缩是有损耗的。渐近式 JPEG 文件支持交错。

    所以对于将Linux中的jpg或者bmp文件转换成ppm.pnm,pbm都可以使用Netpbm库中的程序。

    这里我们将jpg转化成pnm.使用的程序是jpegtopnm。

    电子书里面给的是一个把Macpaint转化成pbm的shell脚本

    1 #!/bin/bash
    2 # cvt.sh:
    3 # 将一个目录下的所有MacPaint格式的图片文件都转换为"pbm"各式的图片文件.
    4
    5 # 使用"netpbm"包中的"macptopbm"程序进行转换,
    6 #+ 这个程序主要是由Brian Henderson(bryanh@giraffe-data.com)来维护的.
    7 # Netpbm绝大多数Linux发行版的标准套件.
    8
    9 OPERATION=macptopbm
    10 SUFFIX=pbm # 新的文件名后缀.
    11
    12 if [ -n "$1" ]
    13 then
    14 directory=$1 # 如果目录名作为参数传递给脚本...
    15 else
    16 directory=$PWD # 否则使用当前的工作目录.
    17 fi
    18
    19 # 假定目标目录中的所有文件都是MacPaint格式的图像文件,
    20 #+ 并且都是以".mac"作为文件名后缀.
    21
    22 for file in $directory/* # 文件名匹配(filename globbing).
    23 do
    24 filename=${file%.*c} # 去掉文件名的".mac"后缀
    25 #+ ('.*c' 将会匹配
    26 #+ '.'和'c'之间任意字符串).
    27 $OPERATION $file > "$filename.$SUFFIX"
    28 # 把结果重定向到新的文件中.
    29 rm -f $file # 转换后删除原始文件.
    30 echo "$filename.$SUFFIX" # 从stdout输出转换后文件的文件名.
    31 done
    32
    33 exit 0

    在我的电脑上用命令 find / -name "*.jpg"

    发现有很多jpg文件,但没有mac文件。同时我不想把源文件删除,而是把转化格式的文件放在另外一个文件夹中。我修改后的代码如下:

     #!/bin/bash
    
     # 使用"netpbm"包中的"jpegtopnm"程序进行转换,
     #+ 这个程序主要是由Brian Henderson(bryanh@giraffe-data.com)来维护的.
     # Netpbm绝大多数Linux发行版的标准套件.
    
     OPERATION=jpegtopnm
     SUFFIX=pnm # 新的文件名后缀.
    
     if [ -n "$1" ]
     then
     directory=$1 # 如果目录名作为参数传递给脚本...
     else
     directory=$PWD # 否则使用当前的工作目录.
     fi
    if [ -n "$2" ]
    then
      redir=$PWD/$2#如果接受目录作为参数传递给脚本
    else
      mkdir Dirpnm
       redir=$PWD/Dirpnm
    fi 
     # 假定目标目录中的所有文件都是MacPaint格式的图像文件,
     #+ 并且都是以".mac"作为文件名后缀.
    
     for file in $directory/* # 文件名匹配(filename globbing).
     do
     filename=${file%.*g} # 去掉文件名的".jpg"后缀
     #+ ('.*c' 将会匹配
     #+ '.'和'c'之间任意字符串).
     recv=`basename $filename`
    exec 9>$redir/$recv.$SUFFIX    #把这个目录绑定文件描述符
    $OPERATION $file >&9    #重定向到9,注意前面加&
     # 把结果重定向到新的文件中.
    # rm -f $file # 转换后删除原始文件.不删除了
     echo "$filename.$SUFFIX" # 从stdout输出转换后文件的文件名.
     done
    
     exit 0
    

     

    1、写出这个程:首先要清楚 如何重定向。可以使用  exec [n] > filename 来重定向。如果不存在,则创建他。还有一种[n] <> filename 没有用出来

    2、注意这里的filename是在directory下的filename是含有绝对路径的变量。如果我们需要在另外一个路径下转化,则只需要去basename然后在另外一个文件夹下进行重定向。

    3、这个shell脚本的本意是为了学会如果对于字符串进行剪辑${string%substring}会截掉末尾最短的substring。(截掉开头最长的子串用##,开头最短用一个#)而这里的substring=".*g"就是jpg(貌似这个操作用basename也可做到)

    3、使用awk来处理字符串

    awk是功能完整的文本处理语言,使用类似于C的语法。他具有一套操作符和能力集,这里只讲在shell中最有用的一小部分。

    Awk将传递进来的每行输入都分割成域. 默认情况下, 一个域指的就是使用空白分隔的一个连续字符串,不过我们可以修改属性来改变分隔符. Awk将会分析并操作每个分割域. 因为这种特性, 所以awk非常善于处理结构化的文本文件 -- 尤其是表 -- 将数据组织成统一的块, 比如说分成行和列.

    强引用(单引号)和大括号用来包含shell脚本中的awk代码段

    eg:  echo one two | awk '{print $2}'  --->  #two

  • 相关阅读:
    AirFlow性能调优
    AirFlow通过账号密码➕角色权限控制来登陆
    通过Supervisor管理airflow的webserver进程和scheduler进程
    CSS基础一
    html学习
    Linux下MySQL远程链接配置
    搭建Firekylin博客
    Vuejs开发环境搭建及热更新
    templates页面超链接访问Controller方法
    Chrome搜索设置
  • 原文地址:https://www.cnblogs.com/SsoZhNO-1/p/9315871.html
Copyright © 2020-2023  润新知