Unix基础之环境变量

举报
iOS逆向 发表于 2021/10/16 00:43:35 2021/10/16
【摘要】 前言: 第一招 HelloWorld:  echo -n # 不带换行 devzkndeMacBook-Pro:~ devzkn$ echo -n hello kevin hello kevindevzkndeMacBook-Pro:~ dev...

前言:


第一招 HelloWorld: 

echo -n     # 不带换行

  

devzkndeMacBook-Pro:~ devzkn$ echo -n hello kevin

hello kevindevzkndeMacBook-Pro:~ devzkn$ 


第二招 判断:


第一式:if


     
  1. if true
  2. then
  3. echo "Hello World"
  4. else
  5. echo "Bug"
  6. fi
  7. if false
  8. then
  9. echo "Hello World"
  10. elif true
  11. then
  12. echo "Bug"
  13. else
  14. echo "Bee"
  15. fi

判断原理

ifelif会执行它后面跟着的命令,然后看返回值是否为0,如果为0则执行then下面的语句块,否则执行else下面的语句块。

devzkndeMacBook-Pro:~ devzkn$ true

devzkndeMacBook-Pro:~ devzkn$ echo $?

0

devzkndeMacBook-Pro:~ devzkn$ false

devzkndeMacBook-Pro:~ devzkn$ echo $?

1

devzkndeMacBook-Pro:~ devzkn$ 


ps:
  1. truefalse事实上也为一个命令,true的返回码必为0false的返回码必为1
  2. $?shell内置变量,用于存放上一个命令的返回码



第二式:test、[ ] 和 [[ ]]

test[ ][[ ]]实际上都是shell中的命令,执行之后会返回10,而这几个命令与if相结合可以达到我们所需要的许多判断功能,例如测试字符串是否为空的三种写法


    
  1. s=""
  2. if [ -z ${s} ]
  3. then
  4. echo "empty"
  5. fi
  6. if [[ -z ${s} ]]
  7. then
  8. echo "empty"
  9. fi
  10. if test -z ${s}
  11. then
  12. echo "empty"
  13. fi

示例:

devzkndeMacBook-Pro:test devzkn$ cat test.sh

s=$1;

if test -z ${s}


then 

echo "empty"


fi

devzkndeMacBook-Pro:test devzkn$ sh -x test.sh

+ s=

+ test -z

+ echo empty

empty

devzkndeMacBook-Pro:test devzkn$ sh -x test.sh s

+ s=s

+ test -z s

devzkndeMacBook-Pro:test devzkn$ 


ps:1. 在性能方面 [ ] test 性能基本相同, [[ ]] 性能是最高的,为前两者的 5 倍左右(以 -d 运算符测试),所以建议尽量使用 [[ ]] 提高脚本性能。
2. 如果是在 [ ] 中使用 < > ,需要将它们写成 \< \>

其他请详见 man test



第三式:&&、||


&&可以用来对两个判断语句求与;注:只有[[ ]]才允许把&&,||写在里面


小技巧

&&||还可以用来拼接命令,达到按前一个命令成功与否来决定是否执行后一个命令的效果


    
  1. cd /data && ls # 当`cd /data`返回0(即成功)时才执行后面的`ls`
  2. cd /data || cd /root # 当`cd /data`返回非0(即失败)时才执行后面的`cd /root`

示例:

devzkndeMacBook-Pro:test devzkn$ cd ../  &&ls

Desktop Library Pictures mydoc

Documents Movies Public test

Downloads Music demand

devzkndeMacBook-Pro:~ devzkn$ cd test1 || cd test

-bash: cd: test1: No such file or directory

devzkndeMacBook-Pro:test devzkn$



第三招:循环




第一式:for

第一式:for


    
  1. for i in {1..100}
  2. do
  3. echo ${i}
  4. done

注:

  1. {1..100}属于通配的一种写法,展开会是1 2 3 ... 100(1~100以空格隔开)这样的字串。

  2. 例如for i in 1 2 3;这样的语句,for会将123依次赋值于i进行循环,而对于通配的情况,for则会将通配展开后将里面的每一项依次赋值于i进行循环。

    示例1:

    devzkndeMacBook-Pro:test devzkn$ cat test_for.sh

    for i in {1..11}

    do

    echo ${i}

    done

    devzkndeMacBook-Pro:test devzkn$ sh test_for.sh

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11


    ps: 1..$1 就不可以达到通配的效果

    示例2:
    cd ~/trc/$1
    for webxxx in `cat ~/kevin/$2`
        do
            # zmore $webxxx |awk -f ~/kevin/rmline.awk| grep xxxx.action |grep -E "
            
             [0-9]+\**
            " | awk -F '[' '{print $2,$4,$6}'|sed 's/];发送://'|sed 's/]//'
            #more $webxxx |awk -f ~/kevin/rmline.awk| grep xxxx.action |grep -E "
            
             [0-9]+\**
            " | awk -F '[' '{print $2,$4,$6}'|sed 's/];发送://'|sed 's/]//'
    
            #more $webxxx |awk -f ~/kevin/rmline.awk| grep 2201194.d |grep -E "
            
             [0-9]+\**
            " | awk -F '[' '{print $2,$4,$6}'|sed 's/];发送://'|sed 's/]//'
    
            more $webxxx |awk -f ~/kevin/rmline.awk| grep xxx.d |grep -E "
            
             [0-9]+\**
            " | awk -F '[' '{print $2,$4,$6}'|sed 's/];发送://'|sed 's/]//'
     
        done


    反引号(`)之间的命令会被执行,其输出结果会转换成一个变量
    ps: 可使用seq 序列命令

         seq -- print sequences of numbers



    devzkndeMacBook-Pro:test devzkn$ cat test_for.sh

    for i in `seq 1 3 20`

    do

    echo ${i}

    done

    devzkndeMacBook-Pro:test devzkn$ sh test_for.sh

    1

    4

    7

    10

    13

    16

    19



    
            
    1. for ((i = 0; i < 100; i++))
    2. do
    3. echo ${i}
    4. done
    5. for ((i = 0; i < 100; i+= 2))
    6. do
    7. echo ${i}
    8. done

    注:

    以上与C语言式的for循环语法基本相同,区别在于双重括号:(( ))


    第二式:while、until


    
            
    1. i=0
    2. while [[ ${i} -lt 100 ]]
    3. do
    4. echo ${i}
    5. ((i++))
    6. done
    
            
    1. i=0
    2. until [[ ${i} -ge 100 ]]
    3. do
    4. echo ${i}
    5. ((i++))
    6. done

    注:

    whileuntil的判断原理与if是类似的,它会执行并它后面跟着的命令,不同点在于:

    • while是后面语句返回值为0,则执行循环中的语句块,否则跳出循环;
    • until则是后面语句返回值非0,则执行循环中的语句块,否则跳出循环。

    第四招:变量

    第一式:整数

    整数的运算

    方法较多,此处只列举最浅显易懂,并且效率最高的办法——直接将符合C语言语法的表达式放到(( ))中即可达到对整数的计算目的:

    
            
    1. echo $(( 1+1 )) # 最简单的1+1
    2. echo $(( (1+2)*3/4 )) # 表达式中还可以带括号
    3. echo $(( 1<<32 )) # 左移右移也支持,但仅限于-4294967296~4294967296之间的数值
    4. echo $(( 1&3 )) # &、^、|、~ 这样的位操作亦支持
    5. (( i=1+2 )) # 将1+2计算出结果后赋值给i,后续若`echo ${i}`会得到3
    6. (( i++ )) # 变量i自增1
    7. (( i+=3 )) # 变量i自增3
    8. # ... # 还有很多,不再详列

    注:

    进行整数运算的方法还有:expr$[]letshell等内置命令,也可调用bcpython等外部工具进行更复杂的数学运算

    第二式:字符串

    替换

    操作 含义
    ${string/old/new} string中第一个old替换为new
    ${string//old/new} string中所有old替换为new

devzkndeMacBook-Pro:test devzkn$ s="i hate hate kevin\!"

devzkndeMacBook-Pro:test devzkn$ echo $s

i hate hate kevin\!

devzkndeMacBook-Pro:test devzkn$ echo ${s/hate/love}

i love hate kevin\!

devzkndeMacBook-Pro:test devzkn$ s="i hate hate kevin"

devzkndeMacBook-Pro:test devzkn$ echo ${s//hate/love}

i love love kevin


截取子串

操作 含义
${string:n} string从下标n到结尾的子串
${string:n:m} string从下标n开始长度为m的子串
${string::m} string从下标0开始长度为m的子串


通配删除

通配删除,即按通配符,删除掉字符串中符合条件的一部分

操作 含义
${string#pattern} string从左到右删除pattern的最小通配
${string##pattern} string从左到右删除pattern的最大通配
${string%pattern} string从右到左删除pattern的最小通配
${string%%pattern} string从右到左删除pattern的最大通配

注:

  1. 此处通配规则参考通配符一览表
  2. 最小通配和最大通配的区别:     最小通配:符合通配的最小子串     最大通配:符合通配的最大子串 例如string值为/00/01/02/dir,对于通配/*/,其最小通配为/00/,而最大通配/00/01/02/

小技巧

  • 获取文件名:${path##*/} (相当于basename命令的功能)
  • 获取目录名:${path%/*} (相当于dirname命令的功能)
  • 获取后缀名:${path##*.}

devzkndeMacBook-Pro:test devzkn$ s="/Users/devzkn/test.sh"

devzkndeMacBook-Pro:test devzkn$ echo ${s##*/}

test.sh

devzkndeMacBook-Pro:test devzkn$ echo ${s%/*}

/Users/devzkn

devzkndeMacBook-Pro:test devzkn$ echo ${s##*.}

sh




第三式:数组

普通数组


    
  1. a=() # 空数组
  2. a=(1 2 3) # 元素为1,2,3的数组
  3. echo ${#a[*]} # 数组长度
  4. echo ${a[2]} # 下标为2的元素值(下标从0开始)
  5. a[1]=0 # 给下标为1的元素赋值
  6. # 遍历数组
  7. for i in ${a[*]}
  8. do
  9. echo ${i}
  10. done
  11. unset a # 清空数组

关联数组

关联数组可以用于存储key-value型的数据,其功能相当于C++中的mappython中的dict


    
  1. declare -A a # 声明关联数组(必须有此句)
  2. a=(["apple"]="a1" ["banana"]="b2" ["carrot"]="c3") # 初始化关联数组
  3. echo ${#a[*]} # 获取元素个数
  4. echo ${a["carrot"]} # 获取元素值
  5. a["durian"]="d4" # 插入或修改元素
  6. echo ${!a[*]} # 获取所有的key
  7. unset a["banana"] # 删除元素
  8. # 遍历数组(仅value)
  9. for i in ${a[*]}
  10. do
  11. echo ${i}
  12. done
  13. # 遍历数组(key和value)
  14. for key in ${!a[*]}
  15. do
  16. echo "${key} ==> ${a[${key}]}"
  17. done
  18. unset a # 清空数组

注:

  1. 关联数组需要bash 4.0以上版本才支持,选用需慎重。查看bash版本用bash --version
  2. 关联数组必须用declare -A显示声明类型,否则数值会出错。

第四式:将命令执行结果存入变量

` `与$( )

LINE_CNT=`wc -l test.txt`

   
LINE_CNT=$(wc -l test.txt)

   

以上命令均可把wc -l test.txt的结果存入LINE_CNT变量中

注: ` ` 和$( )都只将命令行标准输出的内容存入变量,如果需要将标准错误内容存入变量,需要用到重定向


换行符处理

如果命令执行结果有多行内容,存入变量并打印时换行符会丢失:


devzkndeMacBook-Pro:test devzkn$ ls
test.sh		test_for.sh
devzkndeMacBook-Pro:test devzkn$ cat test_for.sh
for i in `seq 1 3 20`
do
	echo ${i}
done
devzkndeMacBook-Pro:test devzkn$ content=`cat test_for.sh`
devzkndeMacBook-Pro:test devzkn$ echo ${content}
for i in `seq 1 3 20` do echo ${i} done
devzkndeMacBook-Pro:test devzkn$ 

若需要保留换行符,则在打印时必须加上 ""

devzkndeMacBook-Pro:test devzkn$ echo "${content}"

for i in `seq 1 3 20`

do

echo ${i}

done

devzkndeMacBook-Pro:test devzkn$ 









正文(重点)


第五招:重定向

标准输入流、标准输出流、标准错误流

名称 英文缩写 内容 默认绑定位置 文件路径 Shell中代号
标准输入流 stdin 程序读取的用户输入 键盘输入 /dev/stdin 0
标准输出流 stdout 程序的打印的正常信息 终端(terminal), 即显示器 /dev/stdin 1
标准错误流 stderr 程序的错误信息 终端(terminal),, 即显示器 /dev/stderr 2

重定向方式一览表

操作 含义
cmd > file 把 stdout 重定向到 file
cmd >> file 把 stdout 追加到 file
cmd 2> file 把 stderr 重定向到 file
cmd 2>> file 把 stderr 追加到 file
cmd &> file 把 stdout 和 stderr 重定向到 file
cmd > file 2>&1 把 stdout 和 stderr 重定向到 file
cmd >> file 2>&1 把 stdout 和 stderr 追加到 file
cmd file2 cmd cmd 以 file 作为 stdin,以 file2 作为 stdout
cat <>file 以读写的方式打开 file
cmd < file cmd cmd 命令以 file 文件作为 stdin
cmd << delimiter Here document 从 stdin 中读入,直至遇到 delimiter 分界符



第一式:重定向标准输出流(stdout)

把程序打印的内容输出到文件

devzkndeMacBook-Pro:test devzkn$ echo 1+1 >exp.txt

devzkndeMacBook-Pro:test devzkn$ cat exp.txt

1+1


第二式:重定向标准错误流(stderr)

把程序的错误信息输出到文件


devzkndeMacBook-Pro:test devzkn$ ls +++ 2> err*

devzkndeMacBook-Pro:test devzkn$ cat err*

ls: +++: No such file or directory



第三式:重定向标准输入流(stdin)

1. 让程序从文件读取输入

以默认从标准输入读取表达式,并进行数学计算的命令bc为例:



devzkndeMacBook-Pro:test devzkn$ echo 1+1 >exp.txt

devzkndeMacBook-Pro:test devzkn$ cat exp.txt

1+1

devzkndeMacBook-Pro:test devzkn$ bc -q < exp.txt

2





2. 将变量中内容作为程序输入

devzkndeMacBook-Pro:test devzkn$ s="1+1"

devzkndeMacBook-Pro:test devzkn$ bc -q <<< "${s}"

2


3. 将当前shell脚本中的多行内容作为程序的输入

例如在shell中内嵌多行python代码:



devzkndeMacBook-Pro:test devzkn$ cat test_python.sh

python << EOF

print 'hello from python'

print 'hello'+'kevin'


EOF






devzkndeMacBook-Pro:test devzkn$ sh test_python.sh

hello from python

hellokevin




内容中支持shell变量
   

devzkndeMacBook-Pro:test devzkn$ cat test_python.sh

#python << EOF

#print 'hello from python'

#print 'hello'+'kevin'


#EOF

msg="shell variable"


python <<EOF

print '${msg}'

EOF


devzkndeMacBook-Pro:test devzkn$ sh test_python.sh

shell variable


ps:
  1. 以上重定向方法格式为:命令 << EOF (换行)...(换行) EOF,其中的EOF换成其它字符串也是有效的,如:命令 << ABC (换行)...(换行) ABC的,但通用习惯都使用EOF



第六招:管道

一式:管道的基本功能

管道的写法为 cmd1 | cmd2,功能是依次执行cmd1cmd2,并将cmd1的标准输出作为cmd2的标准输入

第二式:管道与while、read组合



devzkndeMacBook-Pro:test devzkn$ cat test_while.sh

line_no=0

cat test.sh |

while read line

do

((line_no++));

echo "${line_no} ${line}"

done

#echo "${line_no}"


devzkndeMacBook-Pro:test devzkn$ sh test_while.sh

1 s=$1;

2 if test -z ${s}

4 then

5 echo "empty"

7 fi



注:

  1. read命令用于从标准输入读取一行并赋值给一个或多个变量,如read LINE会从标准输入读取一行并将整行内容赋值给LINE变量,read A B则会从标准输入读入一行并将这行的第1、2列分别赋值给A、B两个变量(分割符默认为空格或tab,可给IFS赋值来更改分割符) > 2. 末尾注释掉的echo "${LINE_NO}"若执行会输出0,原因是管道中的while语句是执行在子进程中的,不会改变父进程中LINE_NO变量的值

ps:

IFS(Internal Field Seprator),即内部域分隔符,完整定义是“The shell uses the value stored in IFS, which is the space, tab, and newline characters by default, to delimit words for the read and set commands, when parsing output from command substitution, and when performing variable substituioin.”。


第三式:管道与xargs组合

xargs 可以从标准输入读取内容,以之构建并执行另一个命令行

devzkndeMacBook-Pro:test devzkn$ find . -type f -name \*.txt

./err.txt

./exp.txt

devzkndeMacBook-Pro:test devzkn$ find . -type f -name \*.txt | xargs

./err.txt ./exp.txt



  • xargs直接接命令名称,则将从标准输入读取的所有内容合并为一行构建命令行并执行

devzkndeMacBook-Pro:test devzkn$ find . -type f -name \*.txt | xargs ls -l

-rw-r--r--  1 devzkn  staff  35 11  1 22:03 ./err.txt

-rw-r--r--  1 devzkn  staff   4 11  1 22:08 ./exp.txt


  • xargs加上-i参数,则会每读取一行就构建并执行一个命令行,构建命令行时会将{}替换为该行的内容

    
  1. 有待尝试
  2. [casheywen@ubuntu:~]# cat test.txt | xargs -i echo rm {}
  3. rm a
  4. rm b
  5. rm c



第七招:通配




hell通配的原理

如果你的当前目录中有1.txt 2.txt 3.txt三个文件,那么当你执行ls *.txt这条命令,shell究竟为你做了什么?

其实shell会先读取当前目录,然后按*.txt的通配条件过滤得到1.txt 2.txt 3.txt这个文件列表,然后将这个列表作为参数传给ls,即ls *.txt相当于ls 1.txt 2.txt 3.txtls命令本身并不会得到*.txt这样的参数。

注:仅当目录中没有符合 *.txt 通配的文件, shell 才会将 *.txt 这个字符串当作参数直接传给 ls 命令

所以如果需要列出当前目录中所有的txt文件,我们使用echo *.txt也同样可以达到目的:

devzkndeMacBook-Pro:test devzkn$ echo *.txt

err.txt exp.txt



注:对于{ }通配shell不会读取目录并过滤获得文件列表。详细请参考下文

通配符一览表

字符 含义 实例
* 匹配 0 或多个字符 a*b a与b之间可以有任意长度的任意字符, 也可以一个也没有, 如aabcb, axyzb, a012b, ab。
? 匹配任意一个字符 a?b a与b之间必须也只能有一个字符, 可以是任意字符, 如aab, abb, acb, a0b。
[list] 匹配 list 中的任意单一字符 a[xyz]b a与b之间必须也只能有一个字符, 但只能是 x 或 y 或 z, 如: axb, ayb, azb。
[!list]
[^list]
匹配 除list 中的任意单一字符 a[!0-9]b a与b之间必须也只能有一个字符, 但不能是阿拉伯数字, 如axb, aab, a-b。
[c1-c2] 匹配 c1-c2 中的任意单一字符 如:[0-9] [a-z] a[0-9]b 0与9之间必须也只能有一个字符 如a0b, a1b... a9b。
{string1,string2,...} 枚举sring1或string2(或更多)其一字符串 a{abc,xyz,123}b 展开成aabcb axyzb a123b
{c1..c2}
{n1..n2}
枚举c1-c2中所有字符或n1-n2中所有数字 {a..f}展开成a b c d e f
a{1..5} 展开成a1 a2 a3 a4 a5

注:

  1. *?[ ]的通配都会按读取目录并过滤的方式展开通配项目
  2. { }则不会有读取目录的过程,它是通过枚举所有符合条件的通配项直接展开的


devzkndeMacBook-Pro:test devzkn$ ls -l {e..f}*.txt

ls: f*.txt: No such file or directory

-rw-r--r--  1 devzkn  staff  35 11  1 22:03 err.txt

-rw-r--r--  1 devzkn  staff   4 11  1 22:08 exp.txt

devzkndeMacBook-Pro:test devzkn$ echo {e..f}*.txt

err.txt exp.txt f*.txt

devzkndeMacBook-Pro:test devzkn$ 




由上面的命令可见,*通配的结果与目录中存在哪些文件有关系,而{ }的通配结果与目录中存在哪些文件无关。若用{ }进行通配,则有可能将不存在的文件路径作为命令行参数传给程序。


第一式:*

*用于通配文件名或目录名中某一部分为任意内容:



第二式:[ ]

[ ]用于通配文件名或目录名中某个字符为限定范围内或限定范围外的值:



第三式:?

?用于通配文件名中某处一个任意值的字符:



第四式:{ }

{ }也为通配符,用于通配在它枚举范围内的值,由于它是直接展开的,我们可以将它用于批量创建目录或文件,也可以用于生成序列:



生成序列

{ }生成的序列常用于for循环


   
  1. for ip in 192.168.234.{1..255}
  2. do
  3. ping ${ip} -w 1 &> /dev/null && echo ${ip} is Alive
  4. done

以上例子用于查找192.168.234.1~192.168.234.255整个网段能ping通的所有ip










1.1查看环境变量


 env 显示所有的环境变量设置

devzkndeMacBook-Pro:test devzkn$ env

TERM_PROGRAM=Apple_Terminal

SHELL=/bin/bash

TERM=xterm-256color



 echo $ENV_VARIABLE  显示指定环境变量的设置
例:
 echo $PATH
/bin:/etc:/usr/bin:/tcb/bin



1.2 设定环境变量

$ ENV_VARIABLE=XXX;export ENV_VARIABLE
例:
$ PATH=$PATH:$INFORMIXDIR/bin;export PATH  将环境变量PATH设定为原PATH值+$INFORMIXDIR/bin

1.3 取消环境变量设置
$ unset $ENV_VARIABLE
例:
$ set GZJ=gzj;export GZJ  设置环境变量GZJ
$ echo $GZJ
gzj  显示环境变量值

$ unset $GZJ  取消环境变量GZJ的设置
$ echo $GZJ
 已取消



总结







文章来源: kunnan.blog.csdn.net,作者:iOS逆向,版权归原作者所有,如需转载,请联系作者。

原文链接:kunnan.blog.csdn.net/article/details/43734761

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。