IC脚本之Shell

        Shell 是一种命令行解释器,它接受用户输入的命令,并将其转换为操作系统可以执行的指令。它不仅仅是一个简单的命令行界面,还是一个功能强大的脚本编程环境,可以编写自动化任务和复杂的工作流程。主流的shell 环境有 Bash Csh Tcsh , makefile中默认使用的是bash shell。我们可以通过 输入 echo $SHELL查看当前shell类型,使用chsh -s 新shell 路径 更改用户登录的默认shell。

        强列建议所有的变量都要加上“”双引号,见详细介绍连接 防止空值导致错误,或者包含空格以及其他特殊字符的字符串;比如[ $a = “HLL”  ] 如果 $a 为空或者未定义,则出现[ = "HLL"] 左边是空的语法错误;当处理字符串 HH HLL时, 会被shell 解释器理解为[ HH HLL="HLL"] 同样出现了语法错误。

CSH 和shell 区别

1. 变量的定义与赋值

标量变量

         变量可以分为普通变量,环境变量,变量名称可以由字母、数字和下划线组成,但不能以数字开头。BASH 和CSH定义变量方式有些许不同这里分别介绍;

BASH shell

普通变量: 
    a=10, 但是注意“=”左右一定不可以有空格;
    set 显示系统中已经存在的shell变量,以及设置的新变量值
环境变量: 
    export MY_VAR=value
    env 在BASH下打印所有环境命令。

 CSH shell

普通变量:
    set a=10 TCSH SHELL 
    set 会打印所有的通变量
环境变量:
    setenv MY_VAR value TCSH 
    printenv  env 在TCSH下打印所有环境命令。
  • 变量的引用

        使用变量的值只需要在前面增加 "$" 符号就可以了,这里需要注意如果 使用 “  " ” 双引号会保持变量的引用(会用变量的值替换), 如果使用 “ ' ” 单引号则不会对其中的变量进行替换,保持原样输出。 

my_var =10
echo $my_var
当在一个字符串替换变量时候,为了避免模糊或混淆, 需要将{} 限定变量的位置。
echo "${my_var}is niupu"   输出10is niupu

如果使用  '' 
echo '${my_var}is niupu'  输出 ${my_var}is niupu
  •  变量替换

        “变量置换(variable substitution)”是指将变量名替换为其对应值的过程,“变量置换(variable substitution)”是指将变量名替换为其对应值的过程。我们可以通过变量置换将一段字符串以命令的方式运行并获取其返回值。

  •  BASH  字符串内容的替换

        通过 $( cmd )  或者 ` cmd ` 获取c命令的输出并用于后续操作,a=$(date +%D_%T), 当变量名后接其他字符时,需要使用${var}将变量隔开。

${var//hello/HELLO} 将var变量中hello字段替换为HELLO (所有)
${var/hello/HELLO} 将var变量中hello字段替换为HELLO (仅替换一次)

注意var变量和"/"不允许出现空格,否则会语法错误;此外替换的新字符串与"}"之间的空格会认为是
新字符串的一部分。
  • CSHELL 字符串内容替换

        只能通过 `` 完成命令的替换, 捕获命令的输出并用于后续操作,当百年来后接其他字符时,需要使用需要使用${var}将变量隔开。

set sr_arr="hello world"
set dt_arr=($sr_arr:as/o/#/)   将o字符替换为#字符
note 注意如果源字符串包含/字符,可以使用其他字符比如%替换/分隔符

 数组变量

在某些 Shell(如 Bash)中,还支持数组变量的定义和操作,使得能够更方便地处理多个数据项。

对于普通·数组可以通过如下方式定义:

        普通数组 : declare -a ARR1  或者  ARR=(10,20,"apple",“banana")

        通过${ARR1[0]} 即可访问其中的变量。

对于关联数组可以通过如下方式定义:

        关联数组 : declare -A ARR2 它是一种类似于字典的数据形式;

        通过${ARR2[key]}来找到与之”键key“对应的value; ${ARR2{@}}获取所有值。

FRUITS=("Apple" "Orange" "Banana" "Grapes")
echo ${FRUITS[0]}  # 输出数组 FRUITS 的第一个元素 "Apple"
echo ${VEGETABLES[2]}  # 输出数组 VEGETABLES 的第三个元素 "Tomato"

##获取所有元素
echo ${FRUIT[@}}
echo ${FRUIT[*}}

##获取数组长度
echo ${#FRUIT[@}}
echo ${#FRUIT[*}}

# 使用 for 循环遍历 FRUITS 数组
for fruit in "${FRUITS[@]}"
do
    echo "Fruit: $fruit"
done

shell 内建变量

  • $0:脚本本身的名称。
  • $1, $2, …, $n:分别是传递给脚本的第一个、第二个直到第 n 个参数。
  • $@:表示所有的参数列表,每个参数被视为一个单独的字符串。
  • $#:传递给脚本的参数个数
  • $? 在bash中表示上个指令的返回值 0:成功, 1:失败;在cshell中表示变量是否存在。

2. shell 基本运算符

        在 Shell 编程中,使用基本运算符可以进行数学运算、逻辑判断和字符串处理等操作。本文将介绍 Shell 中常用的基本运算符及其使用方法。

算数运算符+   - * /
逻辑运算符

-eq          等于

-ne          不等于

-gt           大于

-lt             小于

-ge          大于等于

-le            小于等于

字符串运算符        

=        字符串相等

!=        字符串不相等

-z        字符串为空

-n        字符串非空

与或非                   

!  ||  && 或者

 or  and 

四则运算表达式

BASH: $[1+3] or $(( 1 + 2 ))or let a=a+1

CSH : @ a=$a + 1  or $(1+2) 注意运算符之间左右都有空格, 注意@只支持整数运算,
           使用bc 进行小数运算  

Shell test命令 for bash 

        在 Shell 脚本编程中,test 命令是一个非常重要的工具,用于检查文件类型和比较值。本文将介绍 test 命令的基本用法、常见选项以及一些实际应用场景,它通常会与if 搭配一起使用。

test 命令的基本用法:

1.  test   条件   
    if test -d file

2. 使用方括号 [] (测试表达式) 表示test 命令。
    if [ -d file ] 

 [ -d sim ] && ( cmd1;cmd2 ) 其中cmd1 和cmd2 分别在不同自shell中进行。
 [ -d sim ] && { cmd1; cmd2;} 其中cmd1 和cmnd2实在最开始创建的同一个子shell中运行。

注意点:

1. 在使用 [ ] 时,操作符 -d  和参数之间需要有空格,否则会出现语法错误; 内部的与或非需要使用 -a -o !。

2. 字符串比较注意引号:为了避免字符串比较时出现意外的行为,建议使用双引号将变量括起来。

3. [[  ]] 支持模式匹配和正则表达式,更加灵活。内部的比较就可以使用  > ,  && , ==(字符串)直接进行比较。

  • bc 命令使用 

        bc支持多种数学函数,包括但不限于平方根、指数、对数等。为了使用这些功能,需要在启动 bc 时加入 -l 选项,这将载入数学库。
精度转换: echo "scale=2;1.233" | bc -l 输出1.23
进制转换: echo "obase=16;ibase=10;12 | bc 输出 C

拓展: 如果想要在shell环境中执行多个命令可以使用 {} 或者 () 运算符。{}代码块会在当前shell执行,{  cmd1;cmd2;cmd3 } , "{" 和命令之间需要又空格, "}"之前需要回车或者分号, 命令之间使用 ”;"分隔, 它可以共享当前shell中设置的变量; (cmd1;cmd2;cmd3) 代码块会在子shell中执行,不能共享当前shell中的变量。

对比 ( ) 会创建子Shell

3. 分支结构

        条件判断在 Shell 脚本中通过 if...else 结构实现,用来根据条件的真假来执行不同的命令或代码块。csh 的condtion 与 then之间不存在 ” ;", bash中的"elif" 在csh中通过”else if"实现。

  • BASH 分支语句
单条件判断:
if condition1 ; then 
   expression1
fi  

多条件判断:
if condition1 ; then
    expression1 
elif condition2 
    expression2
fi 

case分支语句
case $var in 
    "apple")       ;;
    "banana")      ;;
    *)             ;;
esac
;; 指示当前分支执行结束后,不再执行后续分支。
  •  Csh 分支结构
if (condition)  then
    expression 
else if (condition2) then 
    expression2 
endif 


类似c语言 switch case 结构
switch ()
    case A :  cmd breaksw
    case B :  cmd breaksw
    default:  cmd breeaksw
endsw 

while ($# > 0) 
    switch 
        case "hello" : 
            echo "hello" 
            breaksw
        case "...." : 
            echo "....."
            breaksw
        default : 
            echo "this is default" 
            breaksw 
    endsw
end 

4. 循环结构

        Shell 脚本中的循环结构包括 forwhile 和 until 循环,用于重复执行一段代码,直到条件不再满足为止。

  • BASH  循环结构

  1. for循环

for i in "$*" ; do
    expressions
    表达式中可以存在continue 跳回下一次循环, break跳出本次循环。
done 

for (( i=0; i<10; i++)) ; do 

    ## C语言风格循环
done 

拓展:对于$*当不用“”引起来时,它时将命令行参数用数组形式存储;否则表示一个命令行参数组成的字符串(含有空格)。

  2.while 循环

count=1
while [ $count -le 5 ]
do
    echo "Count is $count"
    ((count++))
done
用例通过while 读取文本文件: 这里的IFS用于定义文件读取时以哪种分隔符进行分隔
while IFS='seq' read -r line ; do
    
    expression
done < "src.txt"

在makefile中注意循环结构中都补充;
  • Csh函数

foeach item (数组) 
    
end 

while (condition) 

end 

5. shell函数

        在 Shell 编程中,函数是一种重要的组织代码的方式,它可以帮助我们将复杂的任务分解为更小的模块,并且提高代码的重用性和可维护性。本文将介绍 Shell 函数的基本语法、参数传递、返回值处理以及一些实际应用场景。

        shell 定义函数基本语法:

function_name() {
    # 函数体(命令序列)
}
或者
function_name {
    # 函数体(命令序列)
}

使用: 
function_name argv1 argv2

6. record

  1.  source为再当前shell 执行脚本, bash 和 ../是在新开的子shell中运行。详解shell中source、sh、  bash、./执行脚本的区别_ITPUB博客.
  2. 字符串的切片 ,{1..0} 这种用法目前只有bash 环境支持,csh tcsh是不支持的。
string="Hello, World!"
# 正确的参数扩展
substring=${string:7:5}
echo $substring  # 输出 "World"

# 错误示例:offset不是数字
# substring=${string:word:5}  # 这将报错
  • 查看当前目录下一级层次内所有的.v文件,并执行相应的命令
find ./ -name "*.v" -exec cmd {} \; 
  • shell获取当前执行文件路径的表达式:(放在文件中使用)
$(cd $(dirname ${BASH_SOURCE[0]}) && pwd )   #仅仅bash shell支持
  • 不同硬盘间的快速赋值,可以使用exclude 排除其内部的目录原始目录后不加 “ /"
    表示仅仅将其下的文件而不是整个目录赋值过来。
rsync  -avzp - /原始目录/ /path/     
rsync  -avzp --exclude="a" /原始目录/ /path/    排除a目录
  • 查看限定层级下磁盘使用情况
du -h --max-depth==1 ./   # max-depth 决定展示的层级深度
  • 使用find 获取当前目录下特定的文件的绝对路径,
find ./ -name "*.v" -print0 | xargs -0 readlink -f >> a.fl
这里使用了 -print0 选项来确保 find 命令输出的路径名以 null 字符(\0)分隔,而不是换行符。xargs -0 选项告诉 xargs 以 null 字符作为输入项的分隔符。这样做可以正确处理包含空格、换行符等特殊字符的文件名
  • csh 中插入bash代码段
#!usr/bin/csh
xxx
xxx

#bash code field 
bash <<-'EOF" 
 xxx
 xxx
'EOF'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值