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<字符位置> #指定要比较的字符。
相关推荐
IpdataCloud1 小时前
在线IP查询API与本地离线库,速度与安全如何选型?
运维·服务器·网络
志栋智能1 小时前
超自动化巡检,如何成为业务稳定的“压舱石”?
大数据·运维·网络·人工智能·自动化
困惑阿三1 小时前
全栈服务器运维终极备忘录
运维·服务器·nginx·pm2
optimistic_chen2 小时前
【Vue3入门】自定义指令与插槽详解
linux·运维·服务器·vue.js·前端框架·指令
牛奶咖啡132 小时前
基于Cobbler的系统自动化安装部署——Cobbler的安装部署实践
linux·运维·服务器·cobbler·cobbler的安装配置·cobbler环境检查问题解决·cobbler中导入系统镜像
mounter6252 小时前
深度解析 RDMA 技术的里程碑:基于 DMA-BUF 的 P2P 直接访问(GPU Direct RDMA 新姿势)
linux·运维·服务器·网络·p2p·kernel
南山十一少2 小时前
docker的安装及使用
运维·docker·容器
Willliam_william2 小时前
CentOS 7系统中进行时间/时区设置
linux·运维·centos
李白的天不白2 小时前
linux安装MongoDB
linux·运维·服务器