Java程序员的Linux之路——命令篇

前言

作为一名后端开发人员,总是不可不免的或多或少的要跟服务器去打交道,从一开始最基本的cd、mv、cp、rm常用命令,到编写一连串的shell脚本,踩过的坑总是让人怀疑人生。今天在这里,我将从分别从基础到高级,以及场景分类来给大家分享一下我在日常中使用Linux时积累的一些经验/知识,本文的面向对象主要为后端开发人员,以及部分实施人员,对于前端开发人员,有需求的也可以参考。不作为专业的Linux指导,只作为接触Linux并尝试在日常学习工作中参考使用。

下文中所有的操作环境为centos7.9,具体为:CentOS-7-x86_64-Minimal-2009,使用其它的系统版本的,请仅供参考。

一、基础命令

文件操作

下述几个命令,是日常使用率最高的几个命令,包含了创建文件/目录,查看/写入文件、删除/复制/重命名文件/目录等常规操作。

cp
复制代码
cp /home/a.json /home/t      #将文件复制到另一个目录 文件存在时会提示
\cp /home/a.json /home/t     #将文件复制到另一个目录 强制覆盖
cp -r /home/a /home/b        #复制目录
cp -r * /home/b              #将当前目录下所有的文件和目录,复制到b下面
cp file1 file2 file3 /home/b #将多个文件复制到b下面
mv
复制代码
mv /home/a.json /home/t        #移动文件到另一个目录
mv /home/a.json /home/t/b.json #移动文件到另一个目录 并重命名
\mv /home/a.json /home/t       #移动文件到另一个目录 强制覆盖
mv /home/a /home/b             #重命名目录
rm
复制代码
rm  a.json       #删除文件,删除前会有提示
rm -f a.json     #删除文件,直接删除,没有提示
rm -rf /home/t   #删除目录,直接删除,没有提示
ls
复制代码
ls      #列出当前目录文件
ls -a   #显示所有文件(包括隐藏文件)
ls -t   #文件按时间排序
ls -F   #文件以 "/" 结尾
ls -m   #文件用 "," 隔开
ls -1   # 数字1, 每行列出一个文件,相对ls列在一行来说
ls -r   #倒序排序
ls -R   #递归列出文件目录(子文件也一一列出)
ls -l   #以列显示
ll      #列出文件的详细信息※最为常用
echo
复制代码
echo "It is a test"  #打印出字符串
echo It is a test    #同上
echo $JAVA_HOME      #打印出变量的值
echo "$JAVA_HOME"    #同上
echo '$JAVA_HOME'    #会将$JAVA_HOME作为字符串打印出来
echo -e "OK! \n"     # -e 开启转义,否则就会变成普通字符串来打印出\n
echo -E              #取消反斜杠转义
echo                 #什么都不打印,就只是换一行
echo -n              #不换行输入
cat
复制代码
#将文件内容打印出来
cat test.txt
cat -n test.txt   #打印文件 带行号
cat -b test.txt   #打印文件 带行号 不对空白行编号
cat -s test.txt   #打印文件 当遇到有连续两行以上的空白行,只显示一行的空白行
#文件清空  >是覆盖  >>是追加
cat /dev/null > test.txt
#写入文本到文件
#注意,如果要写入的文本中包含$,则需要用到转义字符\,否则会被解析变量
#其中EOF可以换成其它的标志,哪怕是AAA,但常用EOF
#EOF之间的内容,要注意格式,因为EOF内是什么内容,到文件中就是什么内容,空格、TAB都会带过去。 结果的EOF前面不能有空格,否则不会被当做结束标志
#如果EOF内还需要套EOF,则可以将里面的EOF换成其它的标志
cat > test.txt<<EOF
第一行文本
第二行文本
\$JAVA_HOME
EOF
mkdir
复制代码
mkdir /path                  #创建目录,目录存在会报错
mkdir -p /home/path/path2    #创建目录,如果path不存在,则同时创建。目录存在,则跳过创建
mkdir -p /home/{path,path2}  #批量创建目录
touch
复制代码
touch a.sh       #创建一个文件
touch {1..5}.sh  #批量创建1.sh ~ 5.sh

grep/whereis/find/sed

这几个命令,使用上要比前面的几个命令要高一级,从查找到替换。

grep
复制代码
ps -ef | grep java                #grep用来做过滤,通常结合管道|来使用,例如查看运行着java的程序的进程都有哪些
grep -e "java" test.txt           #过滤出文件中包含 java 的行
grep -e "java" -e "net" test.txt  #批量过滤 多个关键字用 -e 来连接
grep "java \| net" test.txt       #批量过滤,用|连接,因为有双引号,所有加了\转义
grep -v "java" test.txt           #反向过滤,即排除过滤
grep -i "java" test.txt           #忽略大小写过滤
grep -n "java" test.txt           #过滤时,带行号
grep -c "java" test.txt           #过滤出关键字出现的次数
#根据文件内容递归查找目录
grep "java" *                     #在当前目录搜索带'java'行的文件,*表示不限文件类型,也可以加上一个/多个 --include=*.yml 来限制文件类型
grep -r "java" *                  #在当前目录及其子目录下搜索'java'行的文件
grep -l -r "java" *               #在当前目录及其子目录下搜索'java'行的文件,但是不显示匹配的行,只显示匹配的文件
#查找行首或行尾有指定关键字
grep '^a'  test.txt               #过滤行首有a的行
grep '$a'  test.txt               #过滤行尾有a的行 这里因为有$,所以不能用双引号,否则会被当做变量来解析,所以用了单引号
#查找行首是/否英文字母的行
#^ 符号,在字符类符号(括号[])之内与之外是不同的! 在 [] 内代表『反向选择』,在 [] 之外则代表定位在行首的意义!
grep  '^[a-zA-Z]' test.txt        #开头是英文字母
grep  '^[^a-zA-Z]' test.txt       #开头不是英文字母
#行尾结束为小数点 (.) 的行
#特别注意到,因为小数点具有其他意义(底下会介绍),所以必须要使用转义字符(\)来加以解除其特殊意义!
grep '\.$' test.txt
grep -v '^$' test.txt             #过滤掉空行,例如在查看一些配置文件时,可以把空行过滤掉
whereis

whereis命令只能用于程序名的搜索,而且只搜索二进制文件(参数-b)、man说明文件(参数-m)和源代码文件(参数-s)。如果省略参数,则返回所有信息。

复制代码
whereis grep        #返回所有匹配的结果
grep: /usr/bin/grep /usr/share/man/man1/grep.1.gz

whereis -b grep     #返回搜索二进制文件的结果,也就是搜索命令文件
grep: /usr/bin/grep

whereis -m grep     #返回说明文件的结果
grep: /usr/share/man/man1/grep.1.gz
find
复制代码
#语法
find 搜索路径 [选项] 搜索内容

#按照文件名搜索
#-name:按照文件名搜索
find . -name abcde    #在当前目录下查找文件名包含 abcde 的文件
#-iname:按照文件名搜索,不区分文件名大小写
find . -iname abcde   #在当前目录下查找文件名包含 abcde 的文件, 不区分abcde的大小写

#按照文件类型搜索
#-type f:查找普通文件
find . -type f -name "*.conf"  #在当前目录下,查找类型为文件,文件名以.conf结尾的文件
#-type d:查找目录
find . -type d -name "test"    #在当前目录下,查找类型为目录,目录名叫test的目录

#其它详细介绍参考 https://zhuanlan.zhihu.com/p/550924132?utm_id=0

需要注意的是,跟find类似的命令,还有要一个locate命令,但该命令查不到最新变动过的文件

sed

前面几个命令基本都在查找,一般我们使用时,都是还牵扯到替换,类似于java当中的replace

复制代码
# old表示被替换的内容,new表示要替换成的内容
# 其中#也可以换成/或者其它常见的符号,具体换成什么要根本实际的文本来看,例如要替换的文本中包含#则就不能用#
sed 's#old#new#g'

#替换文件中的内容
sed -i 's#old#new#g' test.txt

#删除包含指定内容的行
#以下命令表示删除 test.txt 中,包含 aaa 的所有行
sed -i '/aaa/d' test.txt

#跨行删除,例如将文件中指定开头和结尾的内容删掉
#下面的命令表示将test.txt中,将从#sign_start到#sign_end部分的内容删掉
sed -i "/#sign_start/,/#sign_end/d" test.txt

#批量替换,即批量替换指定目录(及其子目录)中包含指定字符串的文件,可以批量指定文件文件
#其中CONF_FILE_TYPE表示批量指定要扫描的文件类型
#由于sed时可能会报错,因为value可能存在换行等因素,所有为了避免打印出错误信息,特添加了  > /dev/null 2>&1,实际无此需求的话可以不用
#后面的`grep "$KEY" -rl $CONF_FILE_TYPE  .`表示批量的检索指定目录(.表示当前目录)下,指定类型的文件中包含指定字符串的所有文件
CONF_FILE_TYPE="--include=*.yml --include=*.yaml "
sed -i "s#$KEY#$VALUE#g" > /dev/null 2>&1  `grep "$KEY" -rl $CONF_FILE_TYPE  .`

文件解压缩

tar
复制代码
#压缩
# -v 表示详细的列出处理的文件,不想看压缩详情,可以去掉该参数
# cvf  打包后为 .tar
# zcvf 打包后为 .tar.gz
# jcvf 打包后为 .tar.bz2 
tar czvf test.tar.gz  /home/test                         #将/home/test压缩成 test.tar.gz,解压后会包含/home目录
tar czvf test.tar.gz -C /home  test                      #将/home下的test压缩成 test.tar.gz,解压后不包含/home目录
tar czvf - /home/test | split -b 100m - test.tar.gz      #分卷压缩
tar czvf test.tar.gz --exclude=test/logs  -C /home  test #压缩时,排除test下的logs目录
tar czvf test.tar.gz --exclude=test/logs test            #压缩时,排除test下的logs目录

#解压
# xvf  解压 .tar
# zxvf 解压 .tar.gz .tgz
# jxvf 解压 .tar.bz2
tar xzvf test.tar.gz                      #在当前目录解压该包
tar xzvf test.tar.gz -C /home             #将该包解压到 /home 目录
tar xzvf test.tar.gz --strip-components 1 #解压该包时,跳过一层目录。即解压出来后的目录会少掉最上面一层。 
zip
复制代码
#安装zip 系统中默认是不带zip压缩命令的
yum install -y zip

#压缩
zip -r test.zip test   #-r表示递归处理,即将test目录下的所有文件及目录及目录中的文件整个压缩,也就是压缩整个文件夹
#zip目前没有找到合适的命令可以在外面路径压缩,例如我在任何路径执行 zip -r test.zip /home/test ,这个时候压缩的包,解压后会有/home路径
zip -r -s 100m test.zip test #-s表示分卷压缩,单位可以是 k千字节,m兆字节,g千兆字节或t万兆字节

#解压
unzip test.zip           #解压test.zip这个包
unzip -v test.zip        #看看这个包里有什么
unzip -t test.zip        #测试这个包能否正确解压
unzip test.zip -d /home  #解压包到 /home目录
unzip -o test.zip        #解压时覆盖原文件
unzip -n test.zip        #解压时不覆盖原文件

#分卷解压
# 要先将分卷合并,然后才能解压
cat test.z* > test.zip
# 根据文件的时间顺序合包
ls -tr test.z* | xargs -i cat {} >> test.zip             #其中 -t表示根据时间排序,-r表示倒序

#批量解压
for pack in /home/*.zip;  do unzip $pack -d /home; done  #批量解压/home下的zip文件,解压到/home目录二

二、进阶命令

防火墙相关

复制代码
systemctl status firewalld     #查询防火墙状态
systemctl stop firewalld       #关闭防火墙
systemctl start firewalld      #开启防火墙
systemctl disable firewalld    #关闭防火墙的开机自启
systemctl enable firewalld     #开启防火墙开机自启
firewall-cmd --list-prot       #查询防火墙开启的端口号
#开启端口号(操作后要重载防火墙)
firewall-cmd --zone=public --add-port=端口号/tcp --permanent
#批量开启端口号
firewall-cmd --zone=public --add-port=80/tcp --add-port=81/tcp --permanent
firewall-cmd --zone=public --add-port=80~90/tcp --permanent
firewall-cmd --reload          #重载防火墙
#关闭端口(操作后要重载防火墙)
firewall-cmd --zone=public --remove-port=端口号/tcp --permanent
#判断防火墙状态
FIREWALL_STATE=$(firewall-cmd --state)
if [ "$FIREWALL_STATE" == "running" ]; then
 echo ">>> Firewall Is Running !!!"
fi

#判断端口号是否已开通
TEST_PORT=$(firewall-cmd --list-port |grep "端口号/tcp")
if [ "$TEST_PORT" == "" ]; then
 echo "端口号未开通"
fi

网络命令

netstat
复制代码
#安装工具包
yum install -y net-tools

#查询端口监听情况
netstat -anp

#获取nginx监听的端口号
netstat -anp | grep  nginx |grep tcp | grep master | grep -v tcp6|awk '{print Ŭ}'|cut -d ":" -f2 | sort | uniq

#根据nginx监听的端口号来进行防火墙端口开放实例
FIREWALL_STATE=$(firewall-cmd --state)
if [ "$FIREWALL_STATE" == "running" ]; then
 echo ">>> 防火墙开启中,执行开放端口 !!!"
 PORTS=$(netstat -anp | grep  nginx |grep tcp | grep master | grep -v tcp6|awk '{print Ŭ}'|cut -d ":" -f2)
 PORT_ARR=(`echo $PORTS | tr ' ' ' '`) 
 
 #可能存在只有一个端口开放,这个时候array是空
 if [ "$PORTS" == "" ]; then
  echo "nginx可能启动失败了,没有检测到其监听的端口"
  exit 1
 fi
 
 if [ "$PORT_ARR" == "" ]; then
  #说明只开了一个端口
  TEST_PORT=$(firewall-cmd --list-port |grep "$PORTS/tcp")
  if [ "$TEST_PORT" == "" ]; then
   echo "开放端口号:$PORTS"
   firewall-cmd --zone=public --add-port=$PORTS/tcp --permanen
  fi 
 else
  for i in "${!PORT_ARR[@]}"; do
   PORT=${PORT_ARR[i]}
   TEST_PORT=$(firewall-cmd --list-port |grep "$PORT/tcp")
   if [ "$TEST_PORT" == "" ]; then
    echo "开放端口号:$PORT"
    firewall-cmd --zone=public --add-port=$PORT/tcp --permanen
   fi
  done
 fi
 #重载防火墙配置
 echo "重载防火墙"
 firewall-cmd --reload 
fi

#获取所有对外监听的tcp端口号,其中过滤掉tcp6(即ipv6)的,22  3344这两个端口,并且从小到大排序,有兴趣的可以逐步加管道去执行看看各自的结果
netstat -anp | grep tcp | grep -v tcp6 | grep LISTEN | grep -v '127.0.0.1' | awk '{print Ŭ}' | cut -d ':' -f2 | grep -v 22 | grep -v 3344 | sort | uniq
curl
复制代码
#通过curl来判断url是否通
#-I 表示获取head信息
#-m 表示超时时间,单位:秒,即多久后超时, 
#-s 表示silent模式,即不展示请求过程状态
#-o 表示将结果输出到/dev/null中,否则会打印出获取的head信息
#-w 用于在一次完整且成功的操作后输出指定格式的内容到标准输出。输出格式由普通字符串和任意数量的变量组成,输出变量需要按照%{variable_name}的格式
#http_code表示要获取状态码,Url不通时,返回的是000,其它的都表示这个url是通的,即存在的
curl -I -m 1 -s -o /dev/null -w %{http_code} http://baiduuuu.com/

#通过curl发送get请求并带参数,其中 -H表示要给header传参,--data表示要提交的表单数据
curl  "http://127.0.0.1:8848/nacos/v1/cs/configs?&accessToken=SecretKey012345678901234567890123456789012345678901234567890123456789"  -H 'Content-Type: application/x-www-form-urlencoded' --data "dataId=1&group=1&type=1&content=1&tenant=1&namespaceId=1"

#通过curl发送post请求并带参数 -H表示要给header传参,-X表示定义请求方式, -d表示请求的数据体,也就是Body
curl -H "Content-Type: application/json" -X POST -d '{"user_id": "123", "coin":100, "success":1, "msg":"OK!" }' "http://192.168.0.1:8001/test"
wget
复制代码
#安装工具包
yum install -y wget

#下载文件到当前目录
wget https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz

#在后台下载文件到当前目录
wget -b https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz

#批量下载,即将要下载的url都写入filelist.txt中,一行是一个url
wget -i filelist.txt

#下载到指定目录
wget -P /home/test https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz

#下载到指定目录并重命名
wget -O /home/test/abc.tar.gz  https://cn.wordpress.org/wordpress-4.9.4-zh_CN.tar.gz

#更多用法请参考 https://blog.csdn.net/qq_45594628/article/details/134041117
nc

我经常的用法是用它来检测端口

复制代码
#通过nc来判断 默认是TCP,需要UDP,则需要加上-u,具体参考nc命令详解

#安装nc
yum install -y nc

#简单测试看结果,-v表示输出详细信息
nc -v 39.105.162.80 8000

#nc使用实例 检测端口是否通
#-v表示输出详细信息
#-z表示告诉netcat使用0 IO,连接成功后立即关闭连接,不进行数据交换
#-w表示连接和最终网络读取超时 
#2>&1表示将原本输出到stderr中的内容重定向输出到stdout,这样就可以拿到内容处理,类似取jdk版本号时如果想解析java -version返回的内容,也需要做此操作才能传给管道
#wc -l 表示统计行数,也就是统计下nc返回的结果中,有没有出现"No route to host"或者"Connection refused"的,有的话就表示失败了
result=$(nc -v -z -w 5 IP PORT 2>&1|grep -e "No route to host" -e "Connection refused"|wc -l)
if [ $result == 0 ];then
 echo "Success"
else
 echo "Fail"
fi

日常排查问题

日常排查问题时,我用的最多的几个命令基本就这几个 ps/top/wc/cut/awk/sort/uniq

ps
复制代码
# ps命令用来列出系统中当前运行的那些进程(静态查看,如果想看动态的进程情况,可以使用下面的top)
-A #显示所有程序。与 -e 具有同样的效用。
-e #此选项的效果和指定"A"选项相同。
-f #显示UID,PPIP,C与STIME栏位。
a #显示现行终端机下的所有程序,包括其他用户的程序。
u #以用户为主的格式来显示程序状况。
x #显示所有程序,不以终端机来区分。

#最常用的两个组合
ps aux #是用BSD的格式来显示
[root@euler-his ~]# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0 166376 12908 ?        Ss   11:05   0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 16
root           2  0.0  0.0      0     0 ?        S    11:05   0:00 [kthreadd]
root           3  0.0  0.0      0     0 ?        I<   11:05   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I<   11:05   0:00 [rcu_par_gp]
root           6  0.0  0.0      0     0 ?        I<   11:05   0:00 [kworker/0:0H-kblockd]
root           8  0.0  0.0      0     0 ?        I<   11:05   0:00 [mm_percpu_wq]
root           9  0.0  0.0      0     0 ?        S    11:05   0:00 [rcu_tasks_rude_]

ps -ef #标准的格式显示进程的
[root@euler-his ~]# ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 11:05 ?        00:00:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 16
root           2       0  0 11:05 ?        00:00:00 [kthreadd]
root           3       2  0 11:05 ?        00:00:00 [rcu_gp]
root           4       2  0 11:05 ?        00:00:00 [rcu_par_gp]
root           6       2  0 11:05 ?        00:00:00 [kworker/0:0H-kblockd]
root           8       2  0 11:05 ?        00:00:00 [mm_percpu_wq]
root           9       2  0 11:05 ?        00:00:00 [rcu_tasks_rude_]
root          10       2  0 11:05 ?        00:00:00 [rcu_tasks_trace]
top
复制代码
#top命令可以动态的显示进程的状况,我一般在查看某个进程的状态,例如CPU使用情况、内存使用情况时,会使用该命令
top - 17:33:23 up  6:28,  1 user,  load average: 0.00, 0.00, 0.00
Tasks: 235 total,   1 running, 234 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st 
MiB Mem :  79923.8 total,  78827.7 free,   1015.8 used,    815.2 buff/cache     
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.  78908.0 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                             
      1 root      20   0  166376  12908   8628 S   0.0   0.0   0:01.33 systemd                                                                                             
      2 root      20   0       0      0      0 S   0.0   0.0   0:00.01 kthreadd                                                                                            
      3 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_gp                                                                                              
      4 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_par_gp                                                                                          
      6 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker/0:0H-kblockd                                                                                
      8 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 mm_percpu_wq                                                                                        
      9 root      20   0       0      0      0 S   0.0   0.0   0:00.00 rcu_tasks_rude_                                                                                     
     10 root      20   0       0      0      0 S   0.0   0.0   0:00.00 rcu_tasks_trace

#有时为了方便截图,可以将变化时间间隔设置大一些,可以加上-d参数
top -d 10  #表示10秒刷新一次

#如果只想观察某个进行的变化,可以指定进程号
top -p<进程号>

#有时排查问题时,需要查看具体目录,这个时候可以在top中按 c 来显示路径
top - 17:38:36 up  6:33,  1 user,  load average: 0.00, 0.00, 0.00
Tasks: 235 total,   1 running, 234 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st 
MiB Mem :  79923.8 total,  78828.4 free,   1015.1 used,    815.2 buff/cache     
MiB Swap:   4096.0 total,   4096.0 free,      0.0 used.  78908.7 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                             
   2695 root      20   0   26860   5900   3704 R 100.0   0.0   0:00.01 top -d 10                                                                                           
      1 root      20   0  166376  12908   8628 S   0.0   0.0   0:01.33 /usr/lib/systemd/systemd --switched-root --system --deserialize 16                                  
      2 root      20   0       0      0      0 S   0.0   0.0   0:00.01 [kthreadd]                                                                                          
      3 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 [rcu_gp]

#在top中,还可以使用如下命令辅助排查问题
M #根据内存大小排序
P #根据CPU使用率排序(默认是该排序)
wc
复制代码
# wc命令一般作为组合使用,用来统计行数、字数和字节数
-c #统计字节数
[root@localhost ~]# ll
总用量 72040
-rw-------. 1 root root     1555 1月  17 2023 anaconda-ks.cfg
drwxr-xr-x. 3 root root       19 6月   7 14:01 data
-rw-r--r--. 1 root root 73759281 6月   7 10:57 docker-26.1.4.tgz
-rw-r--r--. 1 root root      814 6月   7 16:11 docker-compose.yml
[root@localhost ~]# wc -c docker-compose.yml 
814 docker-compose.yml

-l #统计行数
[root@localhost ~]# wc -l docker-compose.yml 
31 docker-compose.yml

-w #统计字数
[root@localhost ~]# wc -w docker-compose.yml 
59 docker-compose.yml

-L #统计最长行的长度
[root@localhost ~]# wc -L docker-compose.yml 
68 docker-compose.yml

#组合使用,查询有多少java关键字的进程
ps -ef|grep java|grep -v grep |wc -l #其中grep -v grep是为了过滤掉grep进程
[root@localhost ~]# ps -ef|grep java|grep -v grep |wc -l
0
cut
复制代码
-b    #(--bytes): 按字节位置提取。例如,-b 1-3 表示提取每行的第 1 到第 3 个字节。
-c    #(--characters): 按字符位置提取。与 -b 类似,但是在多字节字符环境中,它会以字符为单位进行计数。
-f    #(--fields): 按字段提取。字段是由分隔符(默认为制表符)分隔的文本单元。例如,-f 1,3 表示提取每行的第 1 和第 3 个字段。
-d    #(--delimiter): 指定字段分隔符。默认情况下,字段由制表符分隔。例如,-d ',' 会将逗号作为字段分隔符。
--complement  #补充模式。提取未被 -b, -c, 或 -f 选项指定的部分,即反向提取。

#例如有一个文本data.txt内容如下(#号是为了注释,文本中实际没有#):
#Name,Age,Gender
#Alice,30,Female
#Bob,25,Male
#要提取第二列(年龄),可以使用以下命令:
cut -d ',' -f 2 data.txt
#其中 -d ','表示按照后面逗号作为分隔符, -f 2 表示要提取第二列
awk
复制代码
#AWK 是一种处理文本文件的语言,是一个强大的文本分析工具,在处理文本方面属于三剑客之一(grep、sed、awk),其中
grep #过滤文本
sed  #修改文本
awk  #处理文本
#在实际使用中,awk主要用来格式化,功能过于强大,这里我们只做简单介绍,以辅助日常使用
print #打印
NF  #统计总字段数
$  #取值

#例如有如下文本demo.txt
[root@localhost ~]# cat demo.txt 
aa ad ac
asd sedf qwe
aa wd 
qq
vv dd

[root@localhost ~]# awk '{print NF}' demo.txt 
3
3
2
1
2
# 其中NF表示每行的字段数, print表示打印出来

[root@localhost ~]# awk '{print $NF}' demo.txt 
ac
qwe
wd
qq
dd
#上述命令表示,首先NF是统计每行字段数,加上$之后,就变成了取值,例如第一行NF是3,则相当于ū,$NF就是取第三个字段的值,然后print打印出来
sort
复制代码
#sort 命令用于将文本文件内容加以排序,可针对文本文件的内容,以行为单位来排序.
-b   #忽略每行前面开始出的空格字符。
-c   #检查文件是否已经按照顺序排序。
-d   #排序时,处理英文字母、数字及空格字符外,忽略其他的字符。
-f   #排序时,将小写字母视为大写字母。
-i   #排序时,除了040至176之间的ASCII字符外,忽略其他的字符。
-m   #将几个排序好的文件进行合并。
-M   #将前面3个字母依照月份的缩写进行排序。
-n   #依照数值的大小排序。
-u   #意味着是唯一的(unique),输出的结果是去完重了的。
-o<输出文件> #将排序后的结果存入指定的文件。
-r   #以相反的顺序来排序。
-t<分隔字符> #指定排序时所用的栏位分隔字符。
+<起始栏位>-<结束栏位>  #以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。
[-k field1[,field2]]   #按指定的列进行排序。

#一般使用时,可以结合前面的命令,来对结果进行排序,以便展示排查问题
uniq
复制代码
#该命令通常用进行去重使用。
#例如有如下文本demo.txt:
test 30  
test 30  
test 30  
Hello 95  
Hello 95  
Hello 95  
Hello 95  
Linux 85  
Linux 85

uniq demo.txt:
test 30  
Hello 95  
Linux 85
# 注意!!!! 当重复的行并不相邻时,uniq 命令是不起作用的
# 所以这个时候就需要结合sort命令,先进行排序,然后在uniq去重,例如:
sort demo.txt | uniq

#其它扩展命令
-c           #在每列旁边显示该行重复出现的次数。
-d           #仅显示重复出现的行列。
-f<栏位>      #忽略比较指定的栏位。
-s<字符位置>  #忽略比较指定的字符。
-u   #仅显示出一次的行列。
-w<字符位置> #指定要比较的字符。
相关推荐
大树8815 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠15 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质15 小时前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush415 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行52015 小时前
Linux 11 动态监控指令top
linux
小宇宙Zz15 小时前
Maven依赖冲突
java·服务器·maven
Inhand陈工16 小时前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智16 小时前
ARP代理--工作原理
运维·网络·arp·arp代理
不会C语言的男孩17 小时前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
shushangyun_17 小时前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化