当前位置: 首页 > news >正文

正则表达式与文本三剑客(grep、sed、awk)基础与实践

正则表达式基础与实践

一、正则表达式概述

1. 定义

正则表达式(Regular Expression,简称 RE)是用于描述字符排列和匹配模式的语法规则,核心作用是对字符串进行分割、匹配、查找、替换操作。它本质是 “模式模板”,Linux 工具(如 grep、egrep、awk)可通过该模板过滤文本数据流,最终输出 “匹配的数据” 或 “滤掉的数据”。

2. 应用场景

  • 判断字符串是否符合特定格式(如手机号、邮箱、日期);
  • 从大量文本中提取目标内容(如日志中的 IP 地址、错误信息);
  • 批量替换文本中的指定字符或格式。

3. 组成结构

正则表达式由 普通字符元字符 组成:

  • 普通字符:大小写字母(A-Z、a-z)、数字(0-9)、标点符号(!、@、# 等)及其他常规符号,仅匹配自身;
  • 元字符:具有特殊意义的专用字符,用于规定前导字符的出现模式(如匹配开头、结尾、重复次数等)。

二、基础正则表达式(BRE)

基础正则表达式是正则的核心语法,适用于 grep、sed 等工具,以下是常用元字符及示例:

元字符

功能说明

示例

示例说明

\

转义字符,取消后续特殊符号的含义

\!、\$、\n

匹配 !、$、换行符 \n

^

匹配字符串的开始位置

^a、^the、^#

匹配以 a、the、# 开头的行

$

匹配字符串的结束位置

word$、^$

匹配以 word 结尾的行;^$ 匹配空行

.

匹配除换行符 \n 以外的任意一个字符

lo.k、l..k

匹配 lok(o 和 k 间 1 个任意字符)、lbck(l 和 k 间 2 个任意字符)

*

匹配前面一个字符出现0 次或多次(可重复任意次,包括不出现)

loo*k、lo*k

loo*k 匹配 lk(0 个 o)、lok(1 个 o)、look(2 个 o)等;lo*k 同理

[list]

匹配 list 列表中的任意一个字符(列表可是字符集、范围)

go[ola]d、[a-z]、[0-9]

go[ola]d 匹配 gold、goal、god;[0-9] 匹配任意 1 位数字

[^list]

匹配 list 列表中的任意一个字符(取反)

[^0-9]、[^a-z]

[^0-9] 匹配非数字字符;[^a-z] 匹配非小写字母

\{n\}

匹配前面一个字符恰好 n 次(grep 需加 \,egrep/awk 无需加)

lo\{2\}k、[0-9]\{2\}

lo\{2\}k 匹配 look(o 出现 2 次);[0-9]\{2\} 匹配任意 2 位数字

\{n,\}

匹配前面一个字符不少于 n 次(≥n 次)

lo\{2,\}k、[0-9]\{2,\}

lo\{2,\}k 匹配 look(2 次 o)、loook(3 次 o)等;[0-9]\{2,\} 匹配 2 位及以上数字

\{n,m\}

匹配前面一个字符n 到 m 次(≥n 且 ≤m 次)

lo\{2,3\}k、[0-9]\{2,3\}

lo\{2,3\}k 匹配 look(2 次 o)、loook(3 次 o);[0-9]\{2,3\} 匹配 2-3 位数字

基础正则实践(基于 a.txt 文本)

1. 准备测试文本 a.txt

先创建文本文件,内容如下:

lkloklookloooklooooookloooooaaaklooooooookabbbbcdabbbbcd666ooooloooookoooooolkaoblck
2. 实践案例(grep 命令)

命令

匹配逻辑

输出结果(a.txt 中匹配的行)

grep "loo*k" a.txt

匹配 l 后接任意次 o(0 次及以上),再接 k

lok、look、loook、looooook、looooooook、ooooloooook

grep "lo.k" a.txt

匹配 l 后接 o、1 个任意字符,再接 k

look(o 和 k 间是 o,符合 “1 个任意字符”)

grep "lo.*k" a.txt

匹配 l 后接 o、任意个任意字符(0 次及以上),再接 k

lok、look、loook、looooook、loooooaaak、looooooook、ooooloooook(o 和 k 间可含字母如 aaa)

grep "lo\{2\}k" a.txt

匹配 l 后接 2 次 o,再接 k

look

grep "lo\{2,\}k" a.txt

匹配 l 后接≥2 次 o,再接 k

look、loook、looooook、looooooook、ooooloooook

grep "lo\{2,3\}k" a.txt

匹配 l 后接 2-3 次 o,再接 k

look(2 次 o)、loook(3 次 o)

grep "^a" a.txt

匹配以 a 开头的行

abbbbcd、abbbbcd666、aoblck

grep "6$" a.txt

匹配以 6 结尾的行

abbbbcd666

三、扩展正则表达式(ERE)

扩展正则表达式在基础正则上新增了元字符,功能更灵活,适用于 egrep(grep -E)、awk 等工具(无需对 {}、+ 等元字符转义,grep 需加 \ 转义)。

元字符

功能说明

示例

示例说明

+

匹配前面一个字符出现1 次及以上(至少出现 1 次,区别于 * 的 “0 次及以上”)

lo+k

匹配 lok(1 次 o)、look(2 次 o)、loook(3 次 o)等,不匹配 lk(0 次 o)

?

匹配前面一个字符出现0 次或 1 次(最多出现 1 次)

lo?k

匹配 lk(0 次 o)、lok(1 次 o),不匹配 look(2 次 o)

()

将括号中的字符串作为一个整体(分组),用于批量匹配或重复

l(oo)+k

把 oo 视为整体,匹配 look(1 次 oo)、looook(2 次 oo)等

`

`

逻辑 “或”,匹配 `

` 两侧任意一个表达式

{n}

同基础正则 \{n\},匹配前面字符恰好 n 次(无需转义)

lo{3}k

匹配 loook(o 出现 3 次)

{n,}

同基础正则 \{n,\},匹配前面字符≥n 次(无需转义)

lo{3,}k

匹配 loook(3 次 o)、looooook(5 次 o)等

{n,m}

同基础正则 \{n,m\},匹配前面字符 n-m 次(无需转义)

lo{3,5}k

匹配 loook(3 次 o)、looooook(5 次 o),不匹配 looooooook(6 次 o)

扩展正则实践(基于 a.txt 文本)

使用 egrep 命令(支持扩展正则,无需转义),实践案例如下:

命令

匹配逻辑

输出结果(a.txt 中匹配的行)

egrep "lo+k" a.txt

匹配 l 后接≥1 次 o,再接 k

lok、look、loook、looooook、looooooook、ooooloooook

egrep "lo?k" a.txt

匹配 l 后接 0-1 次 o,再接 k

lk(0 次 o)、lok(1 次 o)、oooooolk(ooooo 后接 o?,即 0-1 次 o,最终匹配 oooooolk)

egrep "l(oo)+k" a.txt

匹配 l 后接≥1 次 oo 组,再接 k

look(1 次 oo)、looooook(2 次 oo)、looooooook(3 次 oo)、ooooloooook(含 oo 组)

`egrep "(oo

ab)" a.txt`

匹配含 oo 或 ab 的行

egrep "lo{3}k" a.txt

匹配 l 后接 3 次 o,再接 k

loook

egrep "lo{3,}k" a.txt

匹配 l 后接≥3 次 o,再接 k

loook、looooook、looooooook、ooooloooook

egrep "lo{3,5}k" a.txt

匹配 l 后接 3-5 次 o,再接 k

loook(3 次 o)、ooooloooook(loooo 即 4 次 o,符合 3-5 次范围)

四、补充实践(基于 b.txt 文本)

1. 准备测试文本 b.txt

创建文本文件,内容如下:

loklo12klo1kloAkloBklookloaklodkabcd1234

2. 案例(基础 / 扩展正则结合)

命令

正则类型

匹配逻辑

输出结果(b.txt 中匹配的行)

grep "[a-zA-Z0-9]k" b.txt

基础

匹配 “字母 / 数字 + k” 的组合

lo1k、loAk、loBk、look、loak、lodk

grep "lo[ABo]k" b.txt

基础

匹配 lo 后接 A/B/o,再接 k

loAk、loBk、look

grep "lo[^a-zA-Z]k" b.txt

基础

匹配 lo 后接 “非字母”,再接 k

lo1k(lo 后是数字 1,非字母)

grep "[^a-zA-Z]" b.txt

基础

匹配含 “非字母” 的行(即含数字、符号等)

lo12k、lo1k、1234

五、工具使用说明

工具

支持的正则类型

特殊说明(元字符转义)

grep

基础正则(BRE)

使用 {n}、{n,}、{n,m} 需加转义 \(如 \{2\});扩展正则需加 -E 参数(grep -E 等价于 egrep)

egrep

扩展正则(ERE)

无需转义 {}、+、?、()、`

awk

扩展正则(ERE)

无需转义,支持所有扩展正则元字符

sed

基础正则(BRE)

使用扩展正则需加 -r 参数

Linux 文本处理三剑客(grep、sed、awk)

一、grep:文本过滤工具

grep 是 Linux 中最基础的文本过滤工具,核心功能是按 “字符串” 或 “正则表达式” 筛选文本行,仅输出匹配的内容,常用于日志分析、配置文件检索等场景。

1. 核心语法

grep [选项] "匹配规则" 目标文件

2. 常用选项与功能

选项

功能说明

示例

无选项

直接匹配包含 “字符串” 的行,输出整行内容

grep "blp5" /tmp/services(输出含 “blp5” 的行)

-v

反向匹配:输出不包含“字符串” 的行

grep -v "udp" /tmp/services(输出不含 “udp” 的行)

-i

忽略大小写:匹配时不区分字母大小写

grep -i "BLP5" /tmp/services(同时匹配 “blp5”“BLP5” 等)

-o

仅显示匹配部分:不输出整行,只打印匹配的字符串

grep -o "48[0-9]\+" /tmp/services(仅输出以 “48” 开头的数字)

-n

显示行号:输出匹配行的行号及内容

grep -n "tcp" /tmp/services(输出含 “tcp” 的行号 + 内容)

-E

支持扩展正则表达式(等价于 egrep)

grep -E "lo{2,3}k" a.txt(匹配 “look”“loook”)

3. 常用匹配规则(结合正则)

匹配规则

功能

示例

^字符串

匹配以 “字符串” 开头的行

grep "^blp5" /tmp/services(输出以 “blp5” 开头的行)

字符串$

匹配以 “字符串” 结尾的行

grep "6$" a.txt(输出以 “6” 结尾的行)

^$

匹配空行

grep -v "^$" /etc/httpd/conf/httpd.conf(过滤配置文件空行)

[字符集]

匹配字符集中的任意一个字符

grep "lo[ABo]k" b.txt(匹配 “loAk”“loBk”“look”)

[^字符集]

匹配字符集中的任意一个字符

grep "lo[^a-z]k" b.txt(匹配 “lo1k”,不匹配 “loak”)

4. 典型场景示例

  • 过滤 Apache 配置文件注释行和空行:
grep -v "^#" /etc/httpd/conf/httpd.conf | grep -v "^$"
  • 从日志中提取 IP 地址(假设日志含 “192.168.x.x” 格式 IP):
grep -o "192\.168\.[0-9]\+\.[0-9]\+" /var/log/access.log

二、sed:流编辑器(文本修改工具)

sed(Stream Editor)是 “流编辑器”,核心功能是按规则逐行处理文本(修改、删除、添加、替换),处理时不直接修改原文件(需 -i 选项),常用于批量修改配置、文本格式化等场景。

sed 的核心逻辑:将文本行逐行读入 “模式空间”(临时缓冲区),按命令处理后输出,再处理下一行,直到文件结束。

1. 核心语法

sed [选项] "地址范围 命令" 目标文件
创建文本文件,内容如下:

cat /tmp/services

nimgtw 		48003/udp 		# Nimbus Gateway
3gpp-cbsp 		48049/t//cp 		# 3GPP Cell Broadcast Service Protocol
isnetserv 		48128/tcp 		# Image Systems Network Services
isnetserv 		48128/udp 		# Image Systems Network Services
blp5 			48129/tcp 		# Bloomberg locator
blp5 			48129/udp 		# Bloomberg locator
com-bardac-dw 	48556/tcp 		# com-bardac-dw
com-bardac-dw 	48556/udp 		# com-bardac-dw
iqobject 		48619/tcp 		# iqobject
iqobject 		48619/udp 		# iqobject

2. 常用选项

选项

功能说明

示例

-n

不打印模式空间:仅输出被命令处理后的行(需配合 p 命令)

sed -n "1,3p" /tmp/services(仅输出 1-3 行)

-i

直接修改原文件:无需重定向,直接覆盖原文件内容(慎用!)

sed -i "s/blp5/test/g" /tmp/services(将原文件中 “blp5” 替换为 “test”)

-e

执行多个命令:一次处理中执行多个 sed 命令

sed -e "1,4d" -e "s/blp5/test/" /tmp/services(先删 1-4 行,再替换字符串)

-f

从文件读取命令:将 sed 命令写入文件,通过 -f 调用

sed -f sed_commands.txt /tmp/services(sed_commands.txt 中存 sed 命令)

-r

支持扩展正则表达式:无需对 {} + 等元字符转义

sed -r "s/(lo{2})k/\1_test/" a.txt(匹配 “look” 并替换为 “loo_test”)

3. 关键概念:地址范围(指定处理哪些行)

sed 通过 “地址范围” 限定命令作用的行,常见格式如下:

地址范围格式

功能

示例

数字

仅处理第 N 行

sed "5d" /tmp/services(删除第 5 行)

数字1,数字2

处理第 N1 行到第 N2 行

sed "1,3p" /tmp/services(打印 1-3 行)

数字,+$N

从第 N 行开始,向后 N 行

sed "/blp5/,+1p" /tmp/services(打印 “blp5” 行及后 1 行)

数字~步长

从第 N 行开始,每 “步长” 行处理一次

sed "1~2d" /tmp/services(删除奇数行,步长 = 2)

/正则/

处理匹配 “正则” 的行

sed "/^blp5/d" /tmp/services(删除以 “blp5” 开头的行)

/正则1/,/正则2/

处理 “正则 1” 匹配行到 “正则 2” 匹配行

sed "/^blp5/,/^com/p" /tmp/services(打印 “blp5” 到 “com” 开头的行)

$

处理最后一行

sed "$d" /tmp/services(删除最后一行)

4. 常用 sed 命令(处理文本的核心操作)

命令

功能

示例

p

打印:输出模式空间中的行(需配合 -n)

sed -n "1~2p" /tmp/services(打印奇数行)

d

删除:删除模式空间中的行,不输出

sed "/udp/d" /tmp/services(删除含 “udp” 的行)

s/旧值/新值/[选项]

替换:将 “旧值” 替换为 “新值”,默认仅替换每行第一个匹配

- s/blp5/test/:替换每行第一个 “blp5” 为 “test”

- s/blp5/test/g:g(全局替换),替换每行所有 “blp5”

- s/48049/&.123/:& 引用匹配内容,将 “48049” 改为 “48049.123”

a \文本

追加:在匹配行下方添加 “文本”

sed "/blp5/a \new_line" /tmp/services(在 “blp5” 行下加 “new_line”)

i \文本

插入:在匹配行上方添加 “文本”

sed "/blp5/i \new_line" /tmp/services(在 “blp5” 行上加 “new_line”)

c \文本

替换行:将匹配行整体替换为 “文本”

sed "/blp5/c \replace_line" /tmp/services(将 “blp5” 行替换为 “replace_line”)

r 文件名

读取文件:将 “文件名” 的内容追加到匹配行下方

sed "/blp5/r a.txt" /tmp/services(在 “blp5” 行下追加 a.txt 内容)

w 文件名

写入文件:将匹配行写入 “文件名”(不影响屏幕输出)

sed "/blp5/w b.txt" /tmp/services(将 “blp5” 行保存到 b.txt)

5. 典型场景示例

  • 批量替换配置文件中的字符串(修改原文件):
sed -i "s/Listen 80/Listen 8080/g" /etc/httpd/conf/httpd.conf
  • 删除日志文件中第 10-20 行的注释(假设注释以 “#” 开头):
sed -i "10,20s/^#//" /var/log/app.log
  • 将文本中 “端口 / 协议” 格式(如 48003/udp)改为 “协议 / 端口”(如 udp/48003):
sed -r "s/(.*)([0-9]+)\/(tcp|udp)(.*)/\1\3\/\2\4/" /tmp/services

三、awk:文本处理编程语言

awk 是功能最强大的文本处理工具,兼具 “编程语言” 特性,支持字段分割、变量运算、条件判断、循环等,核心优势是 “按字段处理文本”(如表格数据、日志的字段提取),常用于数据统计、报表生成等场景。

awk 的核心逻辑:将文本逐行视为 “记录”,每行按 “分隔符” 拆分为多个 “字段”(默认分隔符为空格 / 制表符),通过 $1 $2... 引用字段($0 表示整行)。

1. 核心语法

awk [选项] '模式 { 动作 }' 目标文件
  • 模式:指定处理哪些行(如 BEGIN END、正则、行号范围);
  • 动作:对匹配的行执行的操作(如打印字段、运算、判断)。

2. 常用选项

选项

功能说明

示例

-F 分隔符

指定字段分隔符(默认是空格 / 制表符)

awk -F ":" '{print $1,$3}' /etc/passwd(以 “:” 为分隔符,打印第 1、3 字段)

-v 变量=值

定义 awk 变量(在处理文本前赋值)

awk -v num=5 '$3 > num {print $0}' /etc/passwd(打印第 3 字段大于 5 的行)

-f 文件名

从文件读取 awk 脚本(将 “模式 + 动作” 写入文件)

awk -f script.awk /tmp/services(script.awk 中存 awk 逻辑)

--profile=[文件]

将 awk 命令格式化输出到文件(便于调试)

awk --profile=prof.txt 'BEGIN{print "test"}'(将脚本写入 prof.txt)

3. 核心模式(控制处理范围)

模式

功能

示例

BEGIN { 动作 }

处理文本执行(仅执行一次),常用于初始化变量、打印表头

awk 'BEGIN{print "Service\tPort"; print "==="}' /tmp/services(先打印表头)

END { 动作 }

处理文本执行(仅执行一次),常用于统计结果、打印表尾

awk '{count++} END{print "总行数:"count}' /tmp/services(统计文件总行数)

/正则/

处理匹配 “正则” 的行

awk '/tcp/{print $1,$2}' /tmp/services(打印含 “tcp” 的行的第 1、2 字段)

行号范围

处理指定行号的行

awk '1,3{print $0}' /tmp/services(打印 1-3 行)

条件判断

处理满足条件的行

awk '$2 ~ /48129/{print $0}' /tmp/services(第 2 字段含 “48129” 的行)

4. 常用内置变量(无需定义直接使用)

内置变量

功能

示例

$0

表示当前行的完整内容

awk '{print $0}' /tmp/services(打印整行)

$n

表示当前行的第 n 个字段(n 为数字)

awk -F ":" '{print $1}' /etc/passwd(打印用户名,第 1 字段)

NF

表示当前行的 “字段总数”

awk '{print "当前行字段数:"NF}' /tmp/services(输出每行的字段数)

NR

表示当前行的 “行号”(整个文件的行号)

awk 'NR>5{print NR,$0}' /tmp/services(打印行号大于 5 的行)

FS

字段分隔符(等价于 -F 选项,默认是空格)

awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd(以 “:” 为分隔符)

OFS

输出字段分隔符(默认是空格)

`awk 'BEGIN{FS=":";OFS="

5. 典型场景示例

  • 统计 /etc/passwd 中 UID 大于 1000 的用户数:
awk -F ":" '$3 > 1000 {count++} END{print "普通用户数:"count}' /etc/passwd
  • 从 Apache 访问日志(假设格式为 “IP 时间 请求路径”)中提取访问最多的前 5 个 IP:
awk '{print $1}' /var/log/access.log | sort | uniq -c | sort -nr | head -5
  • 格式化输出 /tmp/services 内容(添加表头、对齐字段):
awk 'BEGIN{print "Service\t\tPort/Protocol\tDescription";print "----------------------------------------"} {printf "%-15s %-15s %s\n", $1, $2, $3}' /tmp/services

结果

Service		Port			Description
===
nimgtw 		48003/udp 	# Nimbus Gateway
3gpp-cbsp 	48049/tcp 	# 3GPP Cell Broadcast Service Protocol
isnetserv 	48128/tcp 	# Image Systems Network Services
isnetserv 	48128/udp 	# Image Systems Network Services
blp5 		48129/tcp 	# Bloomberg locator
blp5 		48129/udp 	# Bloomberg locator
com-bardac-dw 	48556/tcp 	# com-bardac-dw
com-bardac-dw 	48556/udp 	# com-bardac-dw
iqobject 	48619/tcp 	# iqobject
iqobject 	48619/udp 	# iqobject
===
END......
  • 计算文本中第 2 字段(假设是数字)的总和:
awk '{sum += $2} END{print "总和:"sum}' /tmp/services

四、三剑客功能对比与适用场景

工具

核心优势

适用场景

特点

grep

快速过滤文本行

日志检索、关键词匹配、筛选行

功能单一,仅 “过滤”,不修改内容

sed

批量修改文本

字符串替换、行删除 / 添加、格式调整

按 “行” 处理,适合简单修改,不擅长字段运算

awk

字段处理与数据统计

字段提取、数据计算、报表生成、条件判断

按 “字段” 处理,支持编程逻辑,功能最全面

总结:简单筛选用 grep,批量修改用 sed,复杂字段处理或统计用 awk,实际场景中三者常结合使用(如 grep 筛选后用 sed 修改,再用 awk 统计)。


文章转载自:

http://2obMR4wY.wmqrn.cn
http://BJTVOj1V.wmqrn.cn
http://yLlVgXq0.wmqrn.cn
http://90D8VM9S.wmqrn.cn
http://QR69V9cn.wmqrn.cn
http://ceTiePqm.wmqrn.cn
http://FODzDB7A.wmqrn.cn
http://13UmJciA.wmqrn.cn
http://t7DDdYGb.wmqrn.cn
http://RRibjGyn.wmqrn.cn
http://H7JTx7wd.wmqrn.cn
http://8cuJe19n.wmqrn.cn
http://u06vnBhT.wmqrn.cn
http://vbuvKY0Q.wmqrn.cn
http://pdFbhfK6.wmqrn.cn
http://DJpsnbbV.wmqrn.cn
http://vQAg35oP.wmqrn.cn
http://28UcplvO.wmqrn.cn
http://sen5TFRI.wmqrn.cn
http://lKP3zQeJ.wmqrn.cn
http://sGBQyITw.wmqrn.cn
http://I4QgwL5c.wmqrn.cn
http://2LGdpVtc.wmqrn.cn
http://GJAigBdh.wmqrn.cn
http://gPW8zKpx.wmqrn.cn
http://f2bcHGK1.wmqrn.cn
http://RoHD39s6.wmqrn.cn
http://agxzTsaZ.wmqrn.cn
http://CjCVKG0g.wmqrn.cn
http://BZpim5vi.wmqrn.cn
http://www.dtcms.com/a/383800.html

相关文章:

  • JavaWeb--day5--请求响应分层解耦
  • 去卷积:用魔法打败魔法,让图像清晰
  • Java开发者LLM实战——LangChain4j最新版教学知识库实战
  • 算法 --- 哈希表
  • 【科研绘图系列】R语言绘制全球海洋温度对浮游生物分裂率影响的数据可视化分析
  • 141.环形链表
  • C++ 最短路SPFA
  • 一文读懂 Java 注解运行原理
  • Dify开发中系统变量(system)和用户变量(user)的区别
  • 扩散模型之(五)基于概率流ODE方法
  • 【代码模板】Linux内核模块带指针的函数如何返回错误码?(ERR_PTR(-ENOMEM)、IS_ERR(ent)、PTR_ERR(ent))
  • 查询 mysql中 所有的 非空记录字段
  • Spring Bean:不只是“对象”那么简单
  • 快速选中对象
  • ByteDance_FrontEnd
  • 中科方德环境下安装软件的几种方式与解决思路
  • 《一本书读懂 AI Agent》核心知识点总结
  • 【CVPR 2025】LSNet:大视野感知,小区域聚合
  • MyBatis 从入门到精通(第二篇)—— 核心架构、配置解析与 Mapper 代理开发
  • Ubuntu 虚拟机设置双向复制粘贴
  • Lombok添加了依赖缺没有生效
  • 嵌入式开发中的keil常见错误与警告解决方案(部分)
  • ES5 和 ES6 类的实现
  • 设计模式-装饰器模式详解
  • 对AQS的详解
  • 实验-基本ACL
  • 开始 ComfyUI 的 AI 绘图之旅-SDXL文生图和图生图(全网首发,官网都没有更新)(十四)
  • Java可用打印数组方法5中+常用变量转字符串方法
  • ssh远程连接服务器到vscode上“连接失败”
  • SpringBoot -原理篇