用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
              ``''.

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

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:

              <<

结合起来!

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真的是一座宝库,值得反复探索。

你可能感兴趣的:(linux软件,bash,linux)