Linux入门攻坚——19、sed入门、bash脚本编程续

sed:Stream EDitor,流编辑器,行编辑器:实现文本编辑时是逐行进行的。

用法:
    sed [option]... 'script' inputfile...
    script:‘地址命令’,如'1,4d'

sed是将文件内容读取后放入自己的编辑缓存中,这个缓存空间叫做sed的模式空间--pattern space,对缓存中的副本进行的编辑,最终要将模式空间中的内容输出到屏幕(输出流)。

常用选项:
    -n:不输出模式空间中的内容至屏幕。
    -e:多点编辑。
    -f /PATH/TO/SCRIPT_FILE:从指定文件中读取编辑脚本;
    -r:支持使用扩展的正则表达式;
    -i:原处编辑,修改源文件

地址定界:
    (1)不给地址:对全文进行处理;
    (2)单地址:#——指定的行;/pattern/——被此处模式所能匹配的每一行
    (3)地址范围:#,#;  #,+#;  /pat1/,/pat2/;   #,/pat1/
    (4)~:步进:1~2 ——显示奇数行;   2~2 ——显示偶数行

编辑命令:
    d:删除
    p:显示模式空间中的内容
    a \text:在行后面追加文本,支持使用\n实现多行追加
    i \text:在行前面插入文本,支持使用\n实现多行插入
    c \text:替换行为单行或多行文本;
    w /path/to/somefile:保存模式空间中匹配的行内容至指定文件中;
    r /path/from/somefile:读取指定文件的文本流至模式空间中匹配的行后;
    =:为模式空间中的行打印行号;
    !:取反条件;
    s///:支持使用其他分隔符,s@@@,s###,查找替换
        替换标记:g——行内全局替换;p——显示替换成功的行; w /path/to/somefile——保存

sed除了有一个模式空间,还有一个保持空间(hold space)
高级编辑命令:
    h:把模式空间中的内容覆盖至保持空间中;
    H:把模式空间中的内容追加至保持空间中;
    g:从保持空间中取出数据覆盖至模式空间;
    G:从保持空间中取出数据追加至模式空间;
    x:把模式空间中内容与保持空间中的内容进行互换;
    n:读取匹配到的行的下一行至模式空间;
    N:追加匹配到的行的下一行至模式空间;
    d:删除模式空间中的行;
    D:删除多行模式空间中的所有行;

sed -n 'n;p' file  :显示偶数行
sed '1!G;h;$!d' file:逆向显示文件内容
sed '$!N;$!D' file:取文件最后两行
sed '$!d' file:取文件最后一行
sed ‘G’:每一行后加一空白行
sed ‘/^$/d;G’ file:多个空白行合并成一个,每行后加一空白行
sed ‘n;d’ file:显示奇数行
sed -n '1!G;h;$p' file:逆向显示文件中的每一行

Bash脚本编程续

until CONDITION;do
    循环体
done

until与while类似,不同之处是进入条件是CONDITION为false,退出条件是CONDITION为true,正好与while相反。
计算100以内正整数的和:

#!/bin/bash
#
declare -i i=1
declare -i sum=0

until [ $i -gt 100 ]; do
    let sum+=$i
    let i++
done
echo "Sum:$sum"

循环控制语句(用于循环体中):
    continue [N]:让某次循环提前结束,带N提前结束第N层的本次循环,而直接进入下一轮循环
        while CONDITION;do
            CMD1
            ...
            if CONDITION2; then
                continue
            fi
            CMDn
            ...
        done
    break [N]:提前结束循环,或提前结束第N层循环
        while CONDITION;do
            CMD1
            ...
            if CONDITION2; then
                break
            fi
            CMDn
            ...
        done

示例:每隔3秒到系统上获取登录的用户信息,如果user1登录了,则记录于日志中,并退出。

#!/bin/bash
#
read -p "Enter a user name:" username

while true; do
    if who | grep "^$username" &> /dev/null; then
	    break
    fi
    sleep 3
done

echo "$username logged on." >> /tmp/user.log
#!/bin/bash
#
read -p "Enter a user name:" username

until who | grep "^$username" &> /dev/null; do
    sleep 3
done

echo "$username logged on." >> /tmp/user.log

while循环的特殊用法(遍历文件的每一行):
    while read line;do
        循环体
    done < /path/from/somefile
依次读取/path/from/somefile文件中的每一行,且将行赋值给变量line;
示例找出ID号为偶数的所有用户,显示其用户名及ID。
 

#!/bin/bash
#
while read line; do
    if [ $[`echo $line | cut -d: -f3` % 2] -eq 0 ]; then
	    echo -e -n "UserName: `echo $line | cut -d: -f1`\t"
	    echo "UID: `echo $line | cut -d: -f3 `"
    fi
done < /etc/passwd

for循环的特殊格式:
    for((控制变量初始化;条件判断表达式;控制变量的修正表达式));do
        循环体
    done

控制变量初始化:仅在运行到循环代码段时执行一次;
控制变量的修正表达式:每轮循环结束会先进行控制变量修正运算,而后再做条件判断;

示例:显示一个菜单,提示用户输入选项,显示选项内容,菜单如下:
cpu)cpu info
mem)memory info
disk)disk info
quit)quit
 

#!/bin/bash
#
while true; do
cat << EOF
cpu)cpu info
mem)memory info
disk)disk info
quit)quit
=================
EOF

    read -p "Enter a  option: " option
    while [ "$option" != 'c' -a "$option" != 'm' -a "$option" != 'd' -a "$option" != 'q' ]; do
        read -p "Wrong option,Enter again: " option
    done

    if [ "$option" == 'c' ]; then
        lscpu
    elif [ "$option" == 'm' ]; then
        cat /proc/meminfo
    elif [ "$option" == 'd' ]; then
        fdisk -l
    else
        echo "Quit"
        exit 0
    fi
done

case语句:条件判断
    case 变量引用 in
    PAT1)
        分支1
        ;;
    PAT2)
        分支2
        ;;
    。。。。
    *)
        默认分支
        ;;
用case语句实现上例:

#!/bin/bash
#
while true; do
cat << EOF
cpu)cpu info
mem)memory info
disk)disk info
quit)quit
=================
EOF

    read -p "Enter a  option: " option
    while [ "$option" != 'c' -a "$option" != 'm' -a "$option" != 'd' -a "$option" != 'q' ]; do
        read -p "Wrong option,Enter again: " option
    done
    case "$option" in
    c)
	    lscpu
	    ;;
    m)
	    cat /proc/meminfo
	    ;;
    d)
	    fdisk -l
	    ;;
    q)
	    echo "Quit"
	    exit 0
	    ;;
    esac	
done

case支持glob风格的通配符:
    *:任意长度字符;
    ?:任意单个字符;
    []:指定范围内的任意单个字符;
    a|b:a或b

function:函数
    过程式编程:代码重用
        模块化编程
        结构化编程

定义语法一:
function f_name {
    ...函数体...
}

定义语法二:
f_name(){
    ...函数体...
}
调用:函数只有被调用才会执行;
    调用:给定函数名
        函数名出现的地方,会被自动替换为函数代码;

函数的生命周期:被调用时创建,返回时终止;
    使用return命令返回自定义状态结果;0表示成功,1~255表示失败;
    如果没有使用return语句,则返回的状态结果是最后一条语句的执行状态结果。

#!/bin/bash
#
username='myuser'
function myadduser {
    if id $username &> /dev/null; then
	    echo "$username exists."
    else
	    useradd $username
	    [ $? -eq 0 ] && echo "Add $username finished."
    fi
}

myadduser
echo $?

以上脚本,不管是否添加用户成功,输出的$?都是0,因为没有return语句,返回的是最后语句的执行状态结果,用户存在,是echo "$username exists."的执行状态结果,用户不存在,是echo "Add $username finished."的执行状态结果。

示例:写一个脚本,完成如下功能:
1)可接受参数:start,stop,restart,status;
2)如果参数非上述四种之一,提示使用格式后报错;
3)如果是start,则创建/var/lock/subsys/SCRIPT_NAME,并显示“启动成功”;
    注意:如果事先已经启动过,如何处理?
4)如果是stop,则删除/var/lock/subsys/SCRIPT_NAME,并显示“停止成功”;
    注意:如果事先已经停止过或未启动,如何处理?
5)如果是restart,则先stop,再start;
    注意:如果本来没有start,如何处理?
6)如果是status,则判断/var/lock/subsys/SCRIPT_NAME存在性,存在显示“SCRIPT_NAME is running....”,不存在显示“SCRIPT_NAME is stopped”
SCRIPT_NAME为当前脚本名。
 

#!/bin/bash
#
# chkconfig: - 88 12       # 定义服务的运行级别,-表示不定义级别,即所有级别都关闭
# description: add this script to a service 
# 上面两行用于将脚本变成服务脚本,即chkconfig管理
prog=$(basename $0)
lockfile=/var/lock/subsys/$prog

start() {
    if [ -e $lockfile ]; then
	    echo "$prog is running."
	    return 0
    else
	    touch $lockfile
	    [ $? -eq 0 ] && echo "Starting $prog finished."
    fi
}

stop() {
    if [ -e $lockfile ]; then 
	    rm -f $lockfile && echo "Stop $prog ok."
    else
	    echo "$prog is stopped yet."
    fi
}

status() {
    if [ -e $lockfile ]; then
	    echo "$prog is running."
    else
	    echo "$prog is stopped."
    fi
}

myusage() {
    echo "Usage:$prog {start | stop | restart | status}"
}

if [ $# -lt 1 ]; then
    myusage
    exit 1
fi

case $1 in
start)
    start
    ;;
stop)
    stop
    ;;
restart)
    stop
    start
    ;;
status)
    status
    ;;
*)
    myusage
    ;;
esac

函数返回值:
    函数的执行结果返回值;
        1)使用echo或print命令进行输出
        2)函数体中调用命令的执行结果
    函数的退出状态码
        1)默认取决于函数体中执行的最后一条命令的退出状态码;
        2)自定义退出状态码;return

函数可以接受参数:
    传递参数给函数:调用函数时,在函数名后以空白分隔给定参数列表即可;如:func arg1 arg2 ..."
    在函数体当中,可使用$1,$2...调用这些参数;还可以使用$@,$*,$#等特殊变量;

#!/bin/bash
#
function myadduser {
    if [ $# -lt 1 ]; then
	echo "missing arguments."
	return 2
    fi
    if id $1 &> /dev/null; then
	echo "$1 exists."
	return 1
    else
	useradd $1
	[ $? -eq 0 ] && echo "Add $1 finished."
	return 0
    fi
}

myadduser userpp
echo $?

变量作用域:
    本地变量:当前shell进程:为了执行脚本会启动专用的shell进程;因此,本地变量的作用范围是当前shell脚本程序文件;
    局部变量:函数的生命周期:函数结束时变量被自动销毁;函数中局部变量需要使用local来定义;
        如果函数中有局部变量,其名称同本地变量;

函数递归:函数直接或间接调用自身
 

#!/bin/bash
#
fact() {
    if [ $1 -eq 0 -o $1 -eq 1 ]; then
	    echo 1
    else
	    echo $[$1*$(fact $[$1-1])]
    fi
}

fact 6

数组:存储多个元素的连续的内存空间
变量:存储单个元素的内存空间;

数组引用:
    数组名
    索引:编号从0开始,属于数值索引
        注意:索引也可以支持使用自定义的格式,而不仅仅是数值格式;
        bashde数组支持稀疏格式;
    引用数组中的元素:${ ARRAY_NAME[INDEX] }

声明数组:declare -a  ARRAY_NAME
                  declare -A  ARRAY_NAME:关联数组:

数组中元素的赋值:
    1)一次只赋值一个元素:ARRAY_NAME[INDEX]=VALUE,weekday[0]=‘Sunday’
    2)一次赋值全部元素:ARRAY_NAME=("VAL1" "VAL2" "VAL3" ...)
    3)只赋值特定元素:ARRAY_NAME=([0]="VAL1" [3]="VAL2" ...)
    4)read -a ARRAY

引用数组元素:$(ARRAY_NAME[INDEX]}
    注意:省略[INDEX]表示引用下标为0的元素;
    所有元素:${ARRAY_NAME[@]},${ARRAY_NAME[*]}
    ${ARRAY_NAME[@]:offset:number}:offset,要跳过的元素个数,number,要取的元素个数,切片(类似python中的切片)
数组的长度(数组中元素的个数):${#ARRAY_NAME[*]},${#ARRAY_NAME[@]}

向数组中增加元素:
    ARRAY[${#ARRAY[*]}]

删除数组中的某元素:
    unset ARRAY[INDEX]

关联数组:
    declare -A ARRAY_NAME
    ARRAY_NAME=([index_name1]='val1'  [index_name2]='val2' ... )

bash的字符串处理工具

字符串切片:${var:offset:number}
取字符串的最右侧几个字符:${var: -length},注意,冒号后必须有一个空白字符
基于模式取子串:
    ${var#*word}:word可以是指定的任意字符,功能:自左而右,查找var变量所存储的字符串中,第一次出现的word,删除字符串开头至第一次出现word字符之间的所有字符;
    ${var##*word}:同上,不过删除的是字符串开头至最后一次由word指定字符串之间的所有内容;

    ${var%word*}:word可以是指定的任意字符,功能:自右而左,查找var变量所存储的字符串中,第一次出现的word,删除字符串最后一个字符向左至第一次出现word字符之间的所有字符;
    ${var%%word*}:同上,只不过删除字符串最右侧的字符向左至最后一次出现word字符之间的所有字符;

查找替换:
    ${var/pattern/substi}:查找var所表示的字符串中,第一次被pattern所匹配到的字符串,以substi替换之;
    ${var//pattern/substi}:查找var所表示的字符串中,所有能被pattern所匹配到的字符串,以substi替换之;
     ${var/#pattern/substi}:查找var所表示的字符串中,行首被pattern所匹配到的字符串,以substi替换之;
    ${var/%pattern/substi}:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,以substi替换之;

查找并删除:
    ${var/pattern}:查找var所表示的字符串中,第一次被pattern所匹配到的字符串,删除之;
    ${var//pattern}:查找var所表示的字符串中,所有被pattern所匹配到的字符串,删除之;
    ${var/#pattern}:查找var所表示的字符串中,行首被pattern所匹配到的字符串,删除之;
    ${var/%pattern}:查找var所表示的字符串中,行尾被pattern所匹配到的字符串,删除之;

字符大小写转换:
    ${var^^}:把var中的所有小写字符串转换为大写;
    ${var,,}:把var中的所有大写字符串转换为小写;

变量赋值:
    ${var:-value}:如果var为空或未设置,那么返回value,否则返回var的值;
    ${var:=value}:如果var为空或未设置,,返回value,并赋值value给var,否则,返回var的值;
    ${var:+value}:如果var不空,那么返回value;
    ${var:?error_infp}:果var为空或未设置,那么返回error_info,至错误流,否则,返回var的值;

为脚本程序使用配置文件:
    .(点号)或source
    1)定义文本文件,每行定义“name=value”
    2)在脚本中source此文件即可

/tmp/host.cfg:
HOSTNAME='www.ceshitest.com'

#!/bin/bash
#
[ -r /tmp/host.cfg ] && source /tmp/host.cfg   # source可用.(点号)代替
HOSTNAME=${HOSTNAME:-www.cd.com}

hostname $HOSTNAME

感觉有点类似宏替换

命令:
    mktemp命令:mktemp [OPTION] ... [TEMPLATE]
        TEMPLATE:filename.XXX,X至少出现三个
        -d:创建临时目录
        --tmpdir:指定临时目录位置:--tmpdir=/PATH/TO/SOMEDIR
        mktemp /tmp/test.XXX,

install命令:
    install [OPTION]... [-T] SOURCE DEST
    install [OPTION]...SOURCE... DIRECTORY
    install [OPTION]...-t DIRECTORY SOURCE
    install [OPTION]...-d DIRECTORY...
    选项:直接指定创建目标的权限,属主、属组
        -m MODE
        -o  OWNER
        -g GROUP     


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/556765.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Junit 历史-ApiHug准备-测试篇-008

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace 背景 J…

【人工智能书籍】一本书读懂AIGC:ChatGPT、AI绘画、智能文明与生产力变革(PDF分享)

今天又来给大家推荐一本人工智能方面的书籍<一本书读懂AIGC&#xff1a;ChatGPT、AI绘画、智能文明与生产力变革>。本书以通俗易懂的方式从各个层面介绍了AIGC的基础知识&#xff0c;并辅以大量案例引领读者了解AIGC的应用实践&#xff0c;让读者可以更快速地利用AIGC改善…

02节-51单片机-LED模块

文章目录 1.点亮一个LED灯2.LED闪烁3.LED流水灯 1.点亮一个LED灯 #include <REGX52.H> void main() {P20xFE; //1111 1110while(1){} }2.LED闪烁 增加延时&#xff0c;控制LED的亮灭间隙 延时函数的添加依靠STC-ISP软件的延时函数功能代码自动生成&#xff0c;如图 #i…

递归 python

↵一、简单理解 解决问题的一种方法&#xff0c;它将问题不断的分成更小的子问题&#xff0c;直到子问题可以用普通的方法解决。通常情况下&#xff0c;递归会使用一个不停调用自己的函数。 【注】&#xff1a;每一次递归调用都是在解决一个更小的问题&#xff0c;如此进行下…

数据库管理-第171期 Oracle是用这种方式确保读一致的(20240418)

数据库管理171期 2024-04-18 数据库管理-第171期 Oracle是用这种方式确保读一致的&#xff08;20240418&#xff09;1 基本概念2 用处3 注意事项总结 数据库管理-第171期 Oracle是用这种方式确保读一致的&#xff08;20240418&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#x…

Docker文档阅读笔记-How to Run GUI Based Applications inside Docker?

以后的文档阅读笔记不在一一介绍。以后只总结干货和重点。 Step 1 使用Systemctl命令启动docker服务&#xff1a; systemctl start docker // to start the docker service. systemctl status docker // to check the status . systemctl restart docke…

mybatis创建入门流程体验

mysql数据库中建表 drop table if exists tb_user;create table tb_user(id int primary key auto_increment,username varchar(20),password varchar(20),gender char(1),addr varchar(30) );INSERT INTO tb_user VALUES (1, zhangsan, 123, 男, 北京); INSERT INTO tb_user …

四川易点慧电子商务抖音小店:安全先行,购物无忧

随着互联网的飞速发展&#xff0c;电子商务已成为人们日常购物的重要渠道。抖音小店作为新兴的电商平台&#xff0c;凭借其独特的社交属性和庞大的用户基础&#xff0c;迅速崛起并吸引了众多商家的入驻。在这个背景下&#xff0c;四川易点慧电子商务有限公司&#xff08;以下简…

Android11应用安装未知来源的权限改动

最近开发的App需要下载安装另一个App。这就涉及到了app的安装代码。关于App的安装代码&#xff0c;写了不少&#xff0c;所以这一块觉得不是问题&#xff1a; 判断版本&#xff0c;Android8.0判断是否有未知来源安装全选&#xff0c;没有则打开未知来源安装权限设置界面去开启…

Linux并发程序设计(1):进程的创建和回收

目录 1、基本概念概念 1.1 程序 1.2 进程 1.3 进程的内容 1.4 进程类型 1.5 进程状态 2、常用命令 2.1 查看进程信息 2.2 改变进程优先级 2.2.1 按用户指定的优先级运行进程 2.2.2 改变正在运行进程的优先级 2.3 其他相关指令 3、进程的创建和结束 3.1 子进程创建 3.1.1 …

Odoo讨论+聊天模块:一体化内部协作平台,赋能高效沟通与业务流程协作

Odoo讨论聊天模块&#xff1a;一体化内部协作平台&#xff0c;赋能高效沟通与业务流程协作 Odoo 讨论模块是一个集成了即时通讯、文件共享、业务关联、权限控制等功能于一体的内部协作工具&#xff0c;允许用户通过跨模块的聊天窗口或通过专用的“讨论”面板互相发送消息、分享…

Golang(一):基础、数组、map、struct

目录 hello world 变量 常量&#xff0c;iota 函数 init函数和导包过程 指针 defer 数组和动态数组 固定长度数组 遍历数组 动态数组 len 和 cap 截取 切片的追加 map 四种声明方式 遍历map 删除 查看键是否存在 结构体 声明 作为形参 方法 封装 继承…

笔记软件功能多样的是哪款?做笔记的软件哪个好用

在快节奏的现代生活中&#xff0c;笔记软件已成为我们提高工作效率、记录生活点滴的重要工具。想象一下&#xff0c;在繁忙的工作中&#xff0c;你能够快速记录下关键信息&#xff0c;或在灵感迸发时及时捕捉&#xff0c;这是多么方便高效。 一款功能多样的笔记软件&#xff0…

Syncovery for Mac:高效文件备份和同步工具

Syncovery for Mac是一款专为Mac用户设计的文件备份和同步工具&#xff0c;凭借其高效、安全和易用的特点&#xff0c;深受用户好评。 Syncovery for Mac v10.14.2激活版下载 该软件具备强大的备份功能&#xff0c;支持多种备份方案和数据格式&#xff0c;用户可以根据需求轻松…

Python教学入门:函数

在 Python 中&#xff0c;def 关键字用于定义函数。函数是一段可重用的代码块&#xff0c;用于执行特定的任务或操作。通过定义函数&#xff0c;可以将一段代码封装起来&#xff0c;使其可以在程序中被多次调用&#xff0c;提高代码的复用性和可维护性。 下面是 def 函数定义的…

pandas/python 一个实战小案例

上次写坦克游戏的时候&#xff0c;接触了一点pandas&#xff0c;当时只是简单了解了一下如何遍历行和列并获取值来替换图片&#xff0c;想更多了解pandas。正好有一些数据需要筛选&#xff0c;试试能不能用通过代码实现。虽然总的来说不复杂&#xff0c;但由于原始数据在命名、…

如何训练猫出门不害怕:耐心做好这些训练,轻松get能溜的小猫

一般我们外出见到的都是遛狗的&#xff0c;溜猫的相对少见&#xff0c;一方面是因为猫咪是喜欢安静独处的小动物&#xff0c;另一方面是糟乱的环境也容易引起猫咪的应激。对于是否应该“溜猫”&#xff0c;有两个极端的阵营。一些铲屎官认为应尊重猫的天性&#xff0c;胆小不爱…

如何使用AI写作扩写文章?看完这篇学会扩写

如何使用AI写作扩写文章&#xff1f;在数字化时代的浪潮下&#xff0c;人工智能&#xff08;AI&#xff09;已经深入渗透到我们生活的各个领域&#xff0c;其中&#xff0c;AI写作扩写技术更是以其高效、便捷的特点受到了广大用户的青睐。它不仅极大提升了写作效率&#xff0c;…

Leetcode算法训练日记 | day29

一、递增子序列 1.题目 Leetcode&#xff1a;第 491 题 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&…

硬件?、嘉立创EDA画PCB规则设计

1、打开规则设计 设置单位为mil 点击全部 将安全距离设置为8mil&#xff0c;这个8mil是目前很多生产PCB的工厂可以做的&#xff0c;如果距离设置的更小也就是性能要求更高&#xff0c;相应的生产成本也高元件到元件的距离设置为20mil 2、设置导线的宽度规则&#xff0c;可以对v…