sed语法

基础介绍

sed(Stream Editor),流编辑器。对标准输出文件逐行进行处理

语法

#第一种形式:对命令的结果进行处理
命令 | sed [option] '[pattern] command'

#第二种形式:对文件进行处理
sed [option] '[pattern] command' file

#[pattern] 是匹配模式,匹配到了才会执行command。如果不写pattern,就会对每一行都执行command

option (选项)

sed [option] '[pattern] command' 文件

    -n      只在控制台打印匹配到的行
    -e      直接在命令行进行sed编辑,是【默认选项】
    -f      编辑动作保存在文件中,需要指定文件
    -r      支持拓展正则表达内容
    -i      直接修改文件内容

pattern (匹配模式)详解

sed [option] '[pattern] command' 文件

匹配模式 含义
10command 匹配第10行
10,20command 匹配从第10行开始,到第20行结束
10,+5command 匹配从第10行开始,到第10+5行结束
/pattern1/command 所有匹配到pattern1的行
/pattern1/,/pattern2/command 匹配到pattern1开始,到pattern2结束
10,/pattern1/command 匹配从第10行开始,到匹配到pattern1结束
/pattern1/,10command 匹配到pattern1行开始,到第10行结束
#1. 直接指定行号
    sed -n "17p" file     #打印file文件的第17行
#2.指定起始行号和结束行号
    sed -n "10,20p" file  #打印file文件的10~20行
#3.指定开始行号,以及之后N行
    sed -n "10,+5p" file  #打印file文件的第10行及之后的5行
#4.【常用!】所有正则表达式匹配到的行
    sed - n "/^root/p" file   #打印file文件中以root开头的行
#5.【常用!】从匹配到pattern1的行到pattern2的行
    sed -n "/^ftp/,/^mail/p file" #打印file文件以ftp开头,到匹配pattern2截止
#6.从指定行号开始匹配,直到匹配到pattern1为止
    sed -n "4,/^hdfs/p" file      #打印file文件从第4行开始,到匹配到hdfs结束
#7.从匹配到pattern1开始,直到第n行
    sed -n "/root/,10p" file      =#打印file文件中从匹配到root的行开始,到第10行结束

匹配的时候,可以通过

sed [option] '/pattern1/command;/pattern2/command;/pattern3/command' 文件

的方式一次执行多条处理命令

command(编辑命令)详解

sed [option] '[pattern] command' 文件

类别 编辑命令 含义
查询 p 打印
增加 a 行后追加
i 行前追加
r 外部文件读入,行后追加
w 匹配行写入外部文件
删除 d 删除
修改 s/old/new 将行内第一个old替换为new
s/old/new/g 将行内全部old替换为new
s/old/new/2g 将行内的前2个替换为new
s/old/new/ig 将行内全部old替换为new,且忽略大小写

sed使用案例

使用sed匹配

  • 需求描述:

处理一个类似MySql配置文件my.cnf的文本,示例文件如下所示。

编写脚本实现:

​ 输出文件有几段,并针对每个短可以统计配置参数的个数

预期实现效果:

1:client 2
2: servber 12
3: mysqld 12
4: mysqld_safe 7
5: embedded 8
6: mysqld-5.5 9

思路:

#确定需要定义哪些函数?
    function get_all_segment        #获取所有的段
    function count_itemes_in_segment #每个段中包含配置项的个数

my.cnf

# this is read by the standalone daemon and embedded servers
[client]
port=3306
socket=/tmp/mysql.socket

#ThisSegmentForserver
[server]
innodb_buffer_pool_size=91750M
innodb_buffer_pool_instances=8
innodb_buffer_pool_load_at_startup=1
innodb_buffer_pool_dump_at_shutdown=1
innodb_data_file_path=ibdata1:1G:autoextend
innodb_flush_log_at_trx_commit=1
innodb_log_buffer_size=32M
innodb_log_file_size=2G
innodb_log_files_in_group=2
innodb_max_undo_log_size=4G
innodb_undo_directory=undolog
innodb_undo_tablespaces=95

#thisisonlyforthemysqldstandalonedaemon
[mysqld]
port=3306
socket=/tmp/mysql.sock
basedir=/usr/local/mysql
datadir=/data/mysql
pid-file=/data/mysql/mysql.pid
user=mysql
bind-address=0.0.0.0
sort_buffer_size=16M
join_buffer_size=16M
thread_cache_size=3000
interactive_timeout=600
wait_timeout=600

#ThisSegmentFormysqld_safe
[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid
max_connections=1000
open_files_limit=65535
thread_stack=512K
external-locking=FALSE
max_allowed_packet=32M

#thisisonlyforembeddedserver
[embedded]
gtid_mode=on
enforce_gtid_consistency=1
log_slave_updates
slave-rows-search-algorithms='INDEX_SCAN,HASH_SCAN'
binlog_format=row
binlog_checksum=1
relay_log_recovery=1
relay-log-purge=1

#usethisgroupforoptionsthatolderserversdon'tunderstand
[mysqld-5.5]
key_buffer_size=32M
read_buffer_size=8M
read_rnd_buffer_size=16M
bulk_insert_buffer_size=64M
myisam_sort_buffer_size=128M
myisam_max_sort_file_size=10G
myisam_repair_threads=1
lock_wait_timeout=3600
explicit_defaults_for_timestamp=1
innodb_file_per_table=1

脚本文件:mysql_process.sh

#!/bin/bash
#
#需要注意,正则表达匹配中括号时候,需要加入斜线转义

# 配置文件名和路径
FILE_NAME='./my.cnf'

# 获取所有的段的段名
function get_all_segments
{
    #查找所有以[任意]开头的行,再把左右中括号替换为空,得到的就是段名
  sed -n '/\[.*\]/p' $FILE_NAME | sed -e 's/\[//g' | sed -e 's/\]//g'
}

# 根据段名获取配置项个数
function count_items_in_segment
{
    # 匹配以[参数1]开头,以[任意]结尾的行,排除注释行(#),排除空行($),最后排除所有[任意]的行,剩下的就是我们需要的配置行   
   items=$(sed -n '/\['$1'\]/,/\[.*\]/p' $FILE_NAME | grep -v "^#" | grep -v "^$" | grep -v "\[.*\]")

   index=0
   for item in $items
   do
     index=$(expr $index + 1)
   done

   echo $index
}

#先获取所有段,然后根据段名查看每个段内字段的个数
count=0
for each in  $(get_all_segments)
do
  count=$(($count + 1))
  echo "$count: $each  $(count_items_in_segment $each)"
done

使用sed删除

  • 需求描述
  1. 删除配置文件中所有注释行和空行
  2. 在配置文件中所有不以#开头的行前面添加*号

nginx.conf

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    upstream www_servers {
    server 192.168.1.70:80 weight=1;
    server 192.168.1.80:80 weight=1;
    }

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       192.168.1.129:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        proxy_pass http://www_servers;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $remote_addr;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

执行语句

#删除配置文件中所有注释行和空行
sed -i '/^#/d;/^$/d;/[:blank:]*#/d' ./nginx.conf

#在配置文件中所有不以#开头的行前面添加*号
sed -i 's/^[^#]/\*&/g' nginx.conf

#(&代表反向引用,此处&其实就指匹配到的整行信息,然后我们在前面加*号。如果不使用&,会将非#号开头的行的第一个字符替换成*)
如人饮水,冷暖自知。
最后更新于 2023-08-20