当前位置: 首页 > 科技观察

LinuxBashScripting15分钟进阶教程

时间:2023-03-15 22:27:30 科技观察

这里的技术贴士原创来自谷歌的“马桶测试”(TOTT)。这是一个修订和扩展的版本。脚本安全我所有的bash脚本都以:#!/bin/bashset-onounsetset-oerrexit这避免了两个常见问题:引用未定义的变量(默认值为“”)执行失败需要注意的是,某些Linux命令的某些参数可以强制忽略错误,例如“mkdir-p”和“rm-f”。另请注意,在“errexit”模式下,虽然可以有效捕获错误,但并非所有失败的命令都可以捕获。在某些情况下,无法检测到某些失败的命令。(更多细节请参考这篇文章。)脚本函数在bash中,你可以定义函数,它们可以像其他命令一样自由使用;它们可以使您的脚本更具可读性:ExtractBashComments(){egrep"^#"}catmyscript.sh|ExtractBashComments|wccomments=$(ExtractBashComments&2}log"INFO""amessage"将尽可能多的bash代码移动到函数中,并且只放置全局变量、常量,并调用最外层的“main”。变量注解Bash可以对变量进行有限的注解。最重要的两个注解是:local(函数内部变量)readonly(只读变量)#ausefulidiom:DEFAULT_VALcanbeoverwritten#withanenvironmentvariableofthesamenamereadonlyDEFAULT_VAL=${DEFAULT_VAL:-7}myfunc(){#initializealocalvariablewiththeglobaldefaultlocalsome_var=${ALFAULT}T_V,可以声明以前不是只读变量的变量作为只读变量:x=5x=6readonlyxx=7#failure尝试用local或readonly注释bash脚本中的所有变量。使用$()而不是反引号(`)反引号很难看,而且在某些字体中与反引号非常相似。$()可以内联使用,避免了转义字符的麻烦。#bothcommandsbelowprintout:A-B-C-Decho"A-`echoB-\`echoC-\\\`echoD\\\`\``"echo"A-$(echoB-$(echoC-$(echoD)))"with[[]](双括号)代替[]使用[[]]可以避免文件扩展名异常等问题,并且可以带来很多语法上的改进,还增加了很多新的特性:单括号:["${name}"\>"a"-o${name}\<"m"]双括号[["${name}">"a"&&"${name}"<"m"]]正则表达式/Globbing使用的好处双括号最好在以下示例中显示:t="abc123"[["$t"==abc*]]#true(通配符比较)[["$t"=="abc*"]]#false(文字比较)[["$t"=~[abc]+[123]+]]#true(正则表达式比较)[["$t"=~"abc*"]]#false(文字比较)注意从bash3.2版开始,正则表达式和通配表达式都不能用引号引起来。如果你的表达式中有空格,你可以将它存储在一个变量中:r="ab+"[["abbb"=~$r]]#trueGlobbing模式下的字符串比较也可以用于case语句中:case$tinabc*);;esac字符串操作Bash有多种操作字符串的方法,其中许多是不可取的。基本用户f="path1/path2/file.ext"len="${#f}"#=20(stringlength)#切片操作:${:}or${:<开始>:<长度>}slice1="${f:6}"#="path2/file.ext"slice2="${f:6:5}"#="path2"slice3="${f:-8}"#="file.ext"(注意:"-"前有一个空格)pos=6len=5slice4="${f:${pos}:${len}}"#="path2"替换操作(使用globbing)f="path1/path2/file.ext"single_subst="${f/path?/x}"#="x/path2/file.ext"global_subst="${f//path"?/x}"#="x/x/file.ext"#stringsplittingreadonlyDIR_SEP="/"array=(${f//${DIR_SEP}/})second_dir="${arrray[1]}"#=path2deletetheheadortail(usingglobbing)f="path1/path2/file.ext"#deletethestringheadextension="${f#*.}"#="ext"#贪婪匹配方式删除字符串headfilename="${f##*/}"#="file.ext"#删除字符串taildirname="${f%/*}"#="path1/path2"#贪心匹配方法删除字符串的末尾root="${f%%/*}"#="path1"以避免避免使用临时文件。有些命令需要通过文件名进行参数化,所以不能使用管道。这时,?<()?很有用。它可以接受一个命令并将其转换成文件名等。它是什么:#下载并比较两个网页diff<(wget-O-url1)<(wget-O-url2)还有一个非常有用的“heredocuments”,它允许您在标准输入中输入多行字符串。下面的“MARKER”可以用任何词替换。#任意单词都可以作为分隔符命令<