Shell scripting - bash

136 阅读6分钟

1. What is Bash

Bash是Unix操作系统的默认shell,shell是一种易于使用的用户界面,用户可以轻松的管理操作系统 Bash是linux中最流行的脚本语言,它经历了时间的考验,同样包含了macos和windows中

小缺点: bash不具备面向对象编程的能力

2. Use bash

2.1 echo

# 打印
echo hello
​
# cat 显示文件问题
cat test.txt

创建一个shelltest.sh

# 打印,运行输bash shelltest.sh / ./shelltest.h都可以运行
echo Hello world
​
# 显示默认的shell程序
echo $SHELL# 说明的是使用的哪一个shell
#!/bin/bash# 输入输出
#!/bin/bash
echo Hello world
​
first_name=kx
last_name=z
echo Hello $last_name$first_nameecho What is your first name
read FIRST_NAME
echo where are you from
read COUNTRY
​
echo Your first name is $FIRST_NAME,and you are from $COUNTRY# 命令行参数
# 指的是答应第一第二个参数
#!/bin/bashecho Hello $1 $2

2.2 piping

# 可以把管道前面的输出当成输入放到管道后面的位置
ls -l /usr/bin | grep bash

Output redirection 输出重定向,通常有两个符号,一个是>,另一个是>>

: OVERRIDE,输出的时候会覆盖

: 追加,append

2.3 wc

wc : word count

# 这条指令使用 wc(word count)命令来统计文件 hello.txt 中的单词数(-w 表示统计单词数)。
# 输出结果会包含两个部分:单词数 和 文件名
wc -w hello.txt
​
# 这条指令通过使用输入重定向符号 < 将文件 hello.txt 的内容作为标准输入传递给 wc 命令。
# 输出结果只会显示单词数,不会显示文件名。
# wc : word count ; -w: 统计单词的数量
wc -w < hello.txt
​
# << 和 <<< 的区别
# << 适合接收多行输入, <<< 适合接收单行输入
 cat << EOF
 wc -w <<< "Hello world count"
 
# 返回码是0,说明是true的结果;返回码是1,说明是false的结果
[ hello = hello ]
echo $?
[ 1 -eq 1 ]
echo $?
[ 1 = 0 ]
echo $?

2.4 if elif else

Bash 脚本的开头,#!/bin/bash 是一个称为 shebanghashbang 的行。它用于指定解释器,也就是告诉操作系统使用哪个程序来运行该脚本

${1,,}:这是 Bash 的一种语法,用于将传递给脚本的第一个参数 $1 全部转换为小写。

#!/bin/bashif [ ${1,,} = zkx ]; then
    echo "oh, you are the boss here, welcome"
elif [ ${1,,} = help ]; then
    echo "Just enter your username, duh!"
else
    echo "I don't know who you are, but you are not the right man!"
fi

while循环

* 是通配符,表示任意其他情况(即不匹配上面条件时)。

esaccase 语句的结束标志,与 if 语句的 fi 类似。

#!/bin/bashcase ${1,,} in
    zkx | administrator)
        echo "Hello, you're the boss here"
        ;;
    help)
        echo "Just enter your usrname"
        ;;
    *)
        echo "Hello there, You're not the boss of me. Enter a valid usrname!"
esac

2.5 array数组

() 括号表示这是一个数组。数组中的元素之间用空格分隔。

在 Bash 中,直接使用 $MY_FIRST_LIST 实际上只会输出数组的第一个元素(即 one)。这是因为 $MY_FIRST_LIST 是数组的简写形式,仅表示第一个元素。

${MY_FIRST_LIST[0]} 是用于访问数组中第一个元素的正确方式(数组索引从 0 开始)。

@ 符号表示数组的所有元素。

echo -n $itemecho 命令用于输出 item 的值,-n 选项表示不换行,只输出内容。

MY_FIRST_LIST=(one two three four five)
echo $MY_FIRST_LIST
echo ${MY_FIRST_LIST[@]}
echo ${MY_FIRST_LIST[0]}
# echo -n $item:echo 命令用于输出 item 的值,-n 选项表示不考虑换行符,只输出内容。
# wc -c:wc(word count)命令用于统计字符数。选项 -c 表示计算字符的数量
for item in ${MY_FIRST_LIST[@]}; do echo -n $item | wc -c; done

其他一些for循环的例子

在 Bash 中,使用双引号 " 包裹变量(例如 "${my_list[@]}")有助于处理空格和特殊字符

如果想要不换行,只需要echo -n就行

my_list=("apple" "banana split" "cherry pie" "date")
​
for fruit in "${my_list[@]}"; do
    echo "I like $fruit"
done

以下是一个数字的for循环例子

在 Bash 中,{1..5} 是一种花括号扩展(brace expansion)语法,用于生成一系列的数字或字符串。在这个例子中,{1..5} 表示生成从 1 到 5 的一系列数字。

#!/bin/bash# 遍历数字 1 到 5
for number in {1..5}; do
    echo "Number: $number"
done

2.6 function函数

uptime -p 命令输出系统的运行时间,例如 "up 5 hours, 23 minutes"。

cut -c4- 只保留从第四个字符开始的内容(去掉前面的 "up ")。所以,up 变量将包含如 "5 hours, 23 minutes" 这样的字符串。

uptime -s 命令输出系统启动的时间,例如 "2024-10-02 08:15:23"。

这一部分使用了Here Document(或 Here-doc),它允许在脚本中输入多行文本。cat 命令将输出这些行。

<< EOF 指示输入将继续直到遇到 EOF(这可以是任何标识符,但通常使用 EOF)。

在 Here Document 的内容部分,有以下内容:

-----
This machine has been up for ${up}
It has been running since ${since}
-----
#!/bin/bashshowuptime(){
    up=$(uptime -p | cut -c4-)
    since=$(uptime -s)
    cat << EOF
-----
This machine has been up for ${up}
It has been running since ${since}
-----
EOF
}
showuptime

显示参数的函数

#!/bin/bash
showname(){
    echo hello $1
}
showname zkx

2.7 sed

sed 是 Unix 和 Linux 环境中的一个强大的文本处理工具,全称是 stream editor(流编辑器)。它主要用于对文本进行自动化的编辑和转换,适合处理大规模的文本文件,能够执行替换、插入、删除、和修改等操作。

sed 's/Pineapple/Feta/' test.txt 这个命令的意思是:

  • sed: 调用 sed 工具。
  • s: 指定替换操作(substitute)。
  • Pineapple: 要查找的文本,即原文本 "Pineapple"。
  • Feta: 替换后的文本,即将 "Pineapple" 替换为 "Feta"。
  • test.txt: 要操作的文件名,sed 会对这个文件的内容进行处理。

假设文本

I love Pineapple pizza.
Pineapple is great in fruit salad.
Pineapple Pineapple everywhere.

就可以使用该指令进行替换

sed -i 's/Pineapple/Feta/' test.txt 这个命令中,-i 选项的意思是“in-place”,即直接在文件中进行修改,而不是将修改的结果输出到终端或另存为其他文件。也就是不输出的意思

分隔符不一定使用的是/ ,也可以使用其他分隔符,空格啊,点都可以

2.8 vim中的替换

sed 不能直接在 vim 中使用,因为它们是两个不同的工具,sed 是一个独立的流编辑器,而 vim 是一个文本编辑器。但 vim 有很多与 sed 类似的功能,特别是 vim 的替换命令,它的语法非常接近 sed 的替换命令。

vim 中,你可以使用类似 sed 的命令来执行替换操作。

vim 中使用替换命令:

你可以通过 vim 的命令模式来进行文本替换,语法如下:

:s/查找文本/替换文本/g

这与 sed 的语法几乎相同,下面是一些常见的用法:

  1. 替换当前行中的文本
:s/old_text/new_text/

这个命令会将当前行中的第一个 old_text 替换为 new_text

  1. 全局替换当前行中的所有匹配项
:s/old_text/new_text/g

这个命令会将当前行中的所有 old_text 替换为 new_text

  1. 替换整个文件中的文本
:%s/old_text/new_text/g
  • % 表示整个文件。
  • g 表示全局替换,即一行中的所有匹配都会被替换。
  1. 在指定行范围内替换
:2,5s/old_text/new_text/g

这会将第 2 行到第 5 行中的 old_text 替换为 new_text,并且替换每一行中的所有匹配项。

  1. 确认替换

如果你希望每次替换之前获得确认,可以加上 c 选项:

:%s/old_text/new_text/gc

这样每次发现匹配项时,vim 会询问你是否进行替换。

  1. 忽略大小写

如果你希望在替换时忽略大小写,可以加上 i 选项:

:%s/old_text/new_text/gi

总结:

虽然 sed 不能直接在 vim 中使用,但 vim 的替换命令非常类似于 sed 的语法。vim 的替换命令非常强大,可以在不同范围内执行替换操作,并支持正则表达式,与 sed 一样灵活

2.9 awk

awk 是一种强大的文本处理工具,广泛应用于数据分析和报告生成,特别是在 Unix 和 Linux 环境中。它以其简洁和灵活性而闻名,能够对文本文件按行进行分析和处理,适合处理结构化数据,比如 CSV 或 TSV 文件。

  1. CSV(Comma-Separated Values)
  • 定义:CSV 文件使用逗号(,)作为分隔符,将数据的每一行表示为一条记录,每一列用逗号分隔。

  • 特点

    • 适用于数据表格、数据库导出等。

    • 可以包含文本、数字、日期等多种数据类型。

    • 如果字段中包含逗号或换行符,通常需要使用引号将整个字段括起来。例如:

      "Name","Age","City"
      "Alice",30,"New York"
      "Bob, Jr.",25,"Los Angeles"
      
  • 示例内容

    Name,Age,City
    Alice,30,New York
    Bob,25,Los Angeles
    
  1. TSV(Tab-Separated Values)
  • 定义:TSV 文件使用制表符(\t)作为分隔符,同样将每一行表示为一条记录,每一列用制表符分隔。

  • 特点

    • 与 CSV 类似,但使用制表符作为分隔符,避免了与字段内容冲突的可能性,适合于包含逗号的数据。
    • 通常更易于处理,因为制表符不太可能出现在实际数据中。
  • 示例内容:

    Name    Age City
    Alice   30  New York
    Bob 25  Los Angeles
    

awk '{print $1,$3}' tmnt.txt 这条指令是使用 awk 工具来处理名为 tmnt.txt 的文本文件,具体来说,它的功能是从每一行中提取并打印出第一个和第三个字段(列)。

详细解释:

  1. awk:

    • awk 是一个文本处理工具,用于分析和处理文本数据。
  2. '{print $1,$3}' :

    • 这是 awk 的操作部分,包含了一个动作(action),用于指定要对每一行执行的操作。
    • print:这是 awk 的内置命令,用于输出指定的内容。
    • $1:表示每行的第一个字段(字段通常是以空格或制表符分隔的内容)。
    • $3:表示每行的第三个字段。
    • print 命令中使用逗号 , 会在输出字段之间插入一个空格。
  3. tmnt.txt:

    • 这是要处理的输入文件名。awk 会逐行读取该文件,并对每一行执行指定的操作。

例子:

假设 tmnt.txt 的内容如下:

Donatello 22 Tech
Michelangelo 21 Party
Raphael 23 Fighter

打印最后一行

 awk '{print $NF}' tmnt.txt 

ls和管道的连用

ls -l | awk '{print $1,$2,$3}'