用bash分割字符串

背景

最近负责移植固件升级功能,发现原来的升级脚本将固件的路径名文件名不做区分,导致脚本必须跟固件在同一路径下才能正确调用,殊为不便。
上代码:

sudo mkdir -p /lib/firmware/F260/
sudo cp $1 /lib/firmware/F260/
echo burn $1 to $2 ...
sudo echo F260/$1 > /sys/class/misc/PCIE_SubFpga1/d_${2}_update

脚本命令行第一个参数$1就是固件的路径名,$2是器件名(表明FPGA还是DSP)。
脚本的问题是,最后一行F260/$1默认$1是文件名,但如果固件跟脚本不在同一目录,则$1必然携带目录名,导致Linux下载固件失败。

解决方案:从路径名中提取出文件名

从路径名提取出文件名,就是用/做分隔符,对路径名执行split操作,获得token数组,数组最后一个就是文件名。
为了减少sed/awk等进程启动,考虑直接用bash内置的read子命令-a选项,以及bash的here strings机制,实现这一目标。

用 / 做分隔符

bash默认的分隔符是空格,但用户可以自行修改,修改后的值存在$IFS环境变量里

       IFS    The  Internal  Field  Separator  that  is  used  for  word  splitting  after  expansion and to split lines into words with the read builtin command.  The default value is
              ``<space><tab><newline>''.

为了将路径名分割成一系列的目录名加(最后一个)文件名,我们就要将分隔符改成/

IFS='/'

注意 IFS更改后尽快执行分割字符串操作,完了立即恢复IFS为空格,否则后续的cprm等文件系统操作都会因为文件路径被当作一系列token而报找不到文件

IFS=' '  #分割字符串后立即恢复IFS配置!

read子命令及其 -a选项、-r选项

split函数去哪儿找?read子命令来帮忙!
read子命令从标准输入读出一个个字符串token,然后绑定到一个个name环境变量。如果指定-a选项,则将所有token绑定到aname数组环境变量

       read [-ers] [-a aname]  [name ...]
              One  line  is read from the standard input, or from the file descriptor fd supplied as an argument to the -u option, and the first word is assigned to the first name, the second word to the second name, and so on
              -a aname
                     The  words are assigned to sequential indices of the array variable aname, starting at 0.  aname is unset before any new values are assigned.  Other name arguments are ignored.
              -r     Backslash does not act as an escape character.  The backslash is considered to be part of the line.  In particular, a backslash-newline pair may not be used  as  a line continuation.

-r选项表示将输入字符串中的\当普通字符看待 ,一般可以不用管。

here strings(here documents的一个变体)

用户已经在命令行里填写好路径了,我们不需要再从标准输入读取字符串,于是需要重定向标准输入
here strings正是一种重定向手段,将脚本的标准输入重定向到一个字符串

   Here Strings
       A variant of here documents, the format is:

              <<<word

       The word undergoes brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, and quote  removal.   Pathname  expansion  and word splitting are not performed.  The result is supplied as a single string to the command on its standard input.

结合起来!

IFS='/'
read -ra LIST <<< "$1" 
F=${LIST[-1]}
IFS=' ' #立即恢复IFS的默认值,否则会影响后面的命令!

sudo mkdir -p /lib/firmware/F260/
sudo cp $1 /lib/firmware/F260/
echo burn $F to $2 ...
sudo  echo F260/$F > /sys/class/misc/PCIE_SubFpga1/d_${2}_update

运行示例

dh@dh-desktop:~$ . test.sh /home/dh/7569_32/fpga_mainboard/F266_MBV1.bin firmware_fpga
burn F266_MBV1.bin to firmware_fpga ...

总结

bash真的是一座宝库,值得反复探索。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值