Linux好用的管道命令

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux好用的管道命令相关的知识,希望对你有一定的参考价值。

Linux好用的管道命令


1. 选取命令

grep

  • 用法
grep [-acinv] [--clolor=auto] 查找的字符 查找的文件名
  • 参数
-a 或 --text : 将二进制文件以文本文件的方式查找数据。
-A<显示行数> 或 --after-context=<显示行数> : 除了显示符合范本样式的那一列之外,并显示该行之后的内容。
-b 或 --byte-offset : 在显示符合样式的那一行之前,标示出该行第一个字符的编号。
-B<显示行数> 或 --before-context=<显示行数> : 除了显示符合样式的那一行之外,并显示该行之前的内容。
-c 或 --count : 计算符合样式【查找的字符】的列数。
-C<显示行数> 或 --context=<显示行数>或-<显示行数> : 除了显示符合样式的那一行之外,并显示该行之前后的内容。
-d <动作> 或 --directories=<动作> : 当指定要查找的是目录而非文件时,必须使用这项参数,否则grep指令将回报信息并停止动作。
-e<范本样式> 或 --regexp=<范本样式> : 指定字符串做为查找文件内容的样式。
-E 或 --extended-regexp : 将样式为延伸的正则表达式来使用。
-f<规则文件> 或 --file=<规则文件> : 指定规则文件,其内容含有一个或多个规则样式,让grep查找符合规则条件的文件内容,格式为每行一个规则样式。
-F 或 --fixed-regexp : 将样式视为固定字符串的列表。
-G 或 --basic-regexp : 将样式视为普通的表示法来使用。
-h 或 --no-filename : 在显示符合样式的那一行之前,不标示该行所属的文件名称。
-H 或 --with-filename : 在显示符合样式的那一行之前,表示该行所属的文件名称。
-i 或 --ignore-case : 忽略字符大小写的差别。
-l 或 --file-with-matches : 列出文件内容符合指定的样式的文件名称。
-L 或 --files-without-match : 列出文件内容不符合指定的样式的文件名称。
-n 或 --line-number : 在显示符合样式的那一行之前,标示出该行的列数编号。
-o 或 --only-matching : 只显示匹配PATTERN 部分。
-q 或 --quiet或--silent : 不显示任何信息。
-r 或 --recursive : 此参数的效果和指定"-d recurse"参数相同。
-s 或 --no-messages : 不显示错误信息。
-v 或 --invert-match :反向选择,即显示不包含匹配文本的所有行。
-V 或 --version : 显示版本信息。
-w 或 --word-regexp : 只显示全字符合的列。
-x --line-regexp : 只显示全列符合的列。
-y : 此参数的效果和指定"-i"参数相同。
  • 实例

1)在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令:

​grep test *file​​ 结果如下所示:

$ grep test test* #查找前缀有“test”的文件包含“test”字符串的文件  
testfile1:This a Linux testfile! #列出testfile1 文件中包含test字符的行
testfile_2:This is a linux testfile! #列出testfile_2 文件中包含test字符的行
testfile_2:Linux test #列出testfile_2 文件中包含test字符的行

2)​​以递归的方式查找符合条件的文件​​。例如,查找指定目录​​/etc/acpi​​ 及其​​子目录​​(如果存在子目录的话)下所有文件中包含字符串​​"update"​​的文件,并打印出该字符串所在行的内容,使用的命令为:

grep -r update /etc/acpi

输出结果如下:

$ grep -r update /etc/acpi #以递归的方式查找“etc/acpi”  
#下包含“update”的文件
/etc/acpi/ac.d/85-anacron.sh:# (Things like the slocate updatedb cause a lot of IO.)
Rather than
/etc/acpi/resume.d/85-anacron.sh:# (Things like the slocate updatedb cause a lot of
IO.) Rather than
/etc/acpi/events/thinkpad-cmos:action=/usr/sbin/thinkpad-keys--update

3)​​反向查找​​。前面各个例子是查找并打印出符合条件的行,通过​​"-v"​​参数可以打印出不符合条件行的内容。

查找文件名中包含 test 的文件中不包含test 的行,此时,使用的命令为:

grep -v test *test*

结果如下所示:

$ grep-v test* #查找文件名中包含test 的文件中不包含test 的行  
testfile1:helLinux!
testfile1:Linis a free Unix-type operating system.
testfile1:Lin
testfile_1:HELLO LINUX!
testfile_1:LINUX IS A FREE UNIX-TYPE OPTERATING SYSTEM.
testfile_1:THIS IS A LINUX TESTFILE!
testfile_2:HELLO LINUX!
testfile_2:Linux is a free unix-type opterating system.

cut「分割」

处理的信息以​​行​​为单位

# 用于有特定分隔字符
cut -d 分割符 -f fields
# cut -c 字符区间
  • 参数
-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
-c :以字符为单位取出固定字符区间。
-d :自定义分隔符,默认为制表符,与-f一起使用。
-f :根据-d的分隔符将一段信息分成数段,使用-f表示取出第几段的意思。
-n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的
范围之内,该字符将被写出;否则,该字符将被排除
  • 实例
zhangsan@node01:~$ echo $PATH
/usr/local/anaconda/condabin:/usr/lib/jdk8/jdk1.8.0_212/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/mongodb-3.2.7/bin:/usr/local/anaconda/bin:/usr/local/sqoop-1.4.6_hadoop-2.0.4-alpha/bin:/usr/local/flume-1.7.0/bin:/usr/local/hive-1.2.1/bin:/usr/local/hadoop-2.7.1/sbin:/usr/local/hadoop-2.7.1/bin:/usr/local/hbase-1.1.5/bin
zhangsan@node01:~$
zhangsan@node01:~$ echo $PATH
/usr/local/anaconda/condabin:/usr/lib/jdk8/jdk1.8.0_212/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/usr/local/mongodb-3.2.7/bin:/usr/local/anaconda/bin:/usr/local/sqoop-1.4.6_hadoop-2.0.4-alpha/bin:/usr/local/flume-1.7.0/bin:/usr/local/hive-1.2.1/bin:/usr/local/hadoop-2.7.1/sbin:/usr/local/hadoop-2.7.1/bin:/usr/local/hbase-1.1.5/bin
zhangsan@node01:~$ echo $PATH | cut -d : -f 5
/usr/sbin
zhangsan@node01:~$ echo $PATH | cut -d : -f 3,5
/usr/local/sbin:/usr/sbin
zhangsan@node01:~$ cat f1.txt
hello-world
hello-hadoop
hive-spark
mr-spark
mr-flink
doris
zhangsan@node01:~$ cat f1.txt | cut -c 7- | head -n 2
world
hadoop

2. 排序命令

sort

sort命令进行排序,而且可以根据不同的数据形式来排序​​「文字和数字的排序不一样」​​;其排序的字符与语系的编码有关,建议在排序时,使用​​LANG=C​​来让语系统一

  • 用法
sort [-fbMnrtuk] [文件 or 标准输入stdin]
  • 参数
-b 忽略每行最前面开始的空格字符部分。
-c 检查文件是否已经按照顺序排序。
-d 排序时,处理英文字母、数字及空格字符外,忽略其他的字符。
-f 【忽略大小写】排序时,将小写字母视为大写字母。
-i 排序时,除了040至176之间的ASCII字符外,忽略其他的字符。
-m 将几个排序好的文件进行合并。
-M 将前面3个字母依照月份的缩写进行排序。
-n 依照数值的大小排序(默认是以文字形式排序的)。
-u 意味着是唯一的(unique),输出的结果是去完重了的。(仅出现一行代表)
-o<输出文件> 将排序后的结果存入指定的文件。
-r 以相反的顺序来排序。
-t<分隔字符> 指定排序时所用的栏位分隔字符。
+<起始栏位>-<结束栏位> 以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。
--help 显示帮助。
--version 显示版本信息。
[-k field1[,field2]] 按指定的列进行排序。
  • 实例
zhangsan@node01:~$ cat f1.txt | sort
023
123
456
datax-sqoop
doris-kylin-presto
flume-kafka-flume
hello-hadoop-yarn
hello-world-coder
hive-spark-tez
mr-flink-kafka
mr-spark-impala
zhangsan@node01:~$ cat f1.txt | sort -t - -k 3
023
123
456
datax-sqoop
hello-world-coder
flume-kafka-flume
mr-spark-impala
mr-flink-kafka
doris-kylin-presto
hive-spark-tez
hello-hadoop-yarn
zhangsan@node01:~$ cat f1.txt | sort -t - -k 3 -n
023
123
456
datax-sqoop
doris-kylin-presto
flume-kafka-flume
hello-hadoop-yarn
hello-world-coder
hive-spark-tez
mr-flink-kafka
mr-spark-impala

wc

  • 用法
wc [-lwm]
  • 参数
-c或--bytes或--chars 只显示Bytes数。
-l或--lines 显示行数。
-w或--words 只显示字数。
-m或--chars:显示字符数。
--help 在线帮助。
--version 显示版本信息。
  • 实例

在默认的情况下,wc将计算指定文件的行数、字数,以及字节数。使用的命令为:

wc testfile

先查看testfile文件的内容,可以看到:

$ cat testfile  
Linux networks are becoming more and more common, but scurity is often an overlooked
issue. Unfortunately, in today’s environment all networks are potential hacker targets,
fro0m tp-secret military research networks to small home LANs.
Linux Network Securty focuses on securing Linux in a networked environment, where the
security of the entire network needs to be considered rather than just isolated machines.
It uses a mix of theory and practicl techniques to teach administrators how to install and
use security applications, as well as how the applcations work and why they are necesary.

使用​​wc​​统计,结果如下:

$ wc testfile           # testfile文件的统计信息  
3 92 598 testfile # testfile文件的行数为3、单词数92、字节数598

其中,3 个数字分别表示testfile文件的行数、单词数,以及该文件的字节数。

如果想同时统计多个文件的信息,例如同时统计testfile、testfile_1、testfile_2,可使用如下命令:

wc testfile testfile_1 testfile_2   #统计三个文件的信息

输出结果如下:

$ wc testfile testfile_1 testfile_2  #统计三个文件的信息  
3 92 598 testfile #第一个文件行数为3、单词数92、字节数598
9 18 78 testfile_1 #第二个文件的行数为9、单词数18、字节数78
3 6 32 testfile_2 #第三个文件的行数为3、单词数6、字节数32
15 116 708 总用量 #三个文件总共的行数为15、单词数116、字节数708

uniq

  • 用法
uniq [-ic]
  • 参数
-c或--count 在每列旁边显示该行重复出现的次数。
-d或--repeated 仅显示重复出现的行列。
-f<栏位>或--skip-fields=<栏位> 忽略比较指定的栏位。
-s<字符位置>或--skip-chars=<字符位置> 忽略比较指定的字符。
-u或--unique 仅显示出一次的行列。
-w<字符位置>或--check-chars=<字符位置> 指定要比较的字符。
--help 显示帮助。
--version 显示版本信息。
[输入文件] 指定已排序好的文本文件。如果不指定此项,则从标准读取数据;
[输出文件] 指定输出的文件。如果不指定此选项,则将内容显示到标准输出设备(显示终端)。
  • 实例

文件testfile中第 2、3、5、6、7、9行为相同的行,使用​​uniq​​命令删除重复的行,可使用以下命令:

uniq testfile

testfile中的原有内容为:

$ cat testfile      #原有内容  
test 30
test 30
test 30
Hello 95
Hello 95
Hello 95
Hello 95
Linux 85
Linux 85

使用​​uniq​​命令删除重复的行后,有如下输出结果:

$ uniq testfile     #删除重复行后的内容  
test 30
Hello 95
Linux 85

检查文件并删除文件中重复出现的行,并在行首显示该行重复出现的次数。使用如下命令:

uniq -c testfile 
结果输出如下:

$ uniq -c testfile #删除重复行后的内容
3 test 30 #前面的数字的意义为该行共出现了3次
4 Hello 95 #前面的数字的意义为该行共出现了4次
2 Linux 85 #前面的数字的意义为该行共出现了2次 当重复的行并不相邻时,uniq

命令是不起作用的,即若文件内容为以下时,​​uniq​​命令不起作用:

$ cat testfile1      # 原有内容 
test 30
Hello 95
Linux 85
test 30
Hello 95
Linux 85
test 30
Hello 95
Linux 85

这时我们就可以使用 sort:

$ sort  testfile1 | uniq
Hello 95
Linux 85
test 30

统计各行在文件中出现的次数:

$ sort testfile1 | uniq -c
3 Hello 95
3 Linux 85
3 test 30

在文件中找出重复的行:

$ sort testfile1 | uniq -d
Hello 95
Linux 85
test 30

3. 划分命令 split

  • 用法
split [-bl] file PREFIX
  • 参数
-<行数> : 指定每多少行切成一个小文件
-b<字节> : 指定文件大小切成一个小文件(可加单位)
-l:以行数来进行划分
--help : 在线帮助
--version : 显示版本信息
-C<字节> : 与参数"-b"相似,但是在切 割时将尽量维持每行的完整性
[输出文件名] : 设置切割后文件的前置文件名, split会自动在前置文件名后再加上编号
  • 实例
zhangsan@node01:~$ split -b 300k jobdata.txt out
zhangsan@node01:~$ ll -k out*
-rw-rw-r-- 1 zhangsan zhangsan 307200 10月 1 23:21 outaa
-rw-rw-r-- 1 zhangsan zhangsan 307200 10月 1 23:21 outab
-rw-rw-r-- 1 zhangsan zhangsan 307200 10月 1 23:21 outac
-rw-rw-r-- 1 zhangsan zhangsan 307200 10月 1 23:21 outad
-rw-rw-r-- 1 zhangsan zhangsan 272028 10月 1 23:21 outae

4. 参数代换xargs

  • 用法
xargs [-0epn] command
  • 参数
-0:如果输入的stdin含有特殊字符,例如:`、\\、空格等字符时,这个-0参数可以将它还原成一般字符,这个参数可以用于特殊状态
-a file 从文件中读入作为 stdin
-e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
-p 当每次执行一个argument的时候询问一次用户。
-n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
-t 表示先打印命令,然后再执行。
-i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 ,可以用 代替。
-r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
-s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。
-L num 从标准输入一次读取 num 行送给 command 命令。
-l 同 -L。
-d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。
-x exit的意思,主要是配合-s使用。。
-P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。
  • 实例
zhangsan@node01:~$ cat f1.txt | xargs
hello-world-coder hello-hadoop-yarn hive-spark-tez mr-spark-impala mr-flink-kafka 456 023 doris-kylin-presto 123 flume-kafka-flume datax-sqoop
zhangsan@node01:~$ cat f1.txt | xargs -d -
hello world coder
hello hadoop yarn
hive spark tez
mr spark impala
mr flink kafka
456
023
doris kylin presto
123
flume kafka flume
datax sqoop

zhangsan@node01:~$ cat f1.txt | xargs -d - -n 2
hello world
coder
hello hadoop
yarn
hive spark
tez
mr spark
impala
mr flink
kafka
456
023
doris kylin
presto
123
flume kafka
flume
datax sqoop

读取 stdin,将格式化后的参数传递给命令

假设一个命令为 sk.sh 和一个保存参数的文件 arg.txt:

#!/bin/bash
#sk.sh命令内容,打印出所有参数。

echo $*
arg.txt文件内容:

# cat arg.txt

aaa
bbb
ccc
xargs 的一个选项 -I,使用 -I 指定一个替换字符串 ,这个字符串在 xargs 扩展时会被替换掉,当 -I 与 xargs 结合使用,每一个参数命令都会被执行一次:

# cat arg.txt | xargs -I ./sk.sh -p -l

-p aaa -l
-p bbb -l
-p ccc -l
复制所有图片文件到 /data/images 目录下:

ls *.jpg | xargs -n1 -I cp /data/images
xargs 结合 find 使用

用 rm 删除太多的文件时候,可能得到一个错误信息:/bin/rm Argument list too long. 用 xargs 去避免这个问题:

find . -type f -name "*.log" -print0 | xargs -0 rm -f
xargs -0 将 \\0 作为定界符。

统计一个源代码目录中所有 php 文件的行数:

find . -type f -name "*.php" -print0 | xargs -0 wc -l
查找所有的 jpg 文件,并且压缩它们:

find . -type f -name "*.jpg" -print | xargs tar -czvf images.tar.gz
xargs 其他应用

假如你有一个文件包含了很多你希望下载的 URL,你能够使用 xargs下载所有链接:

# cat url-list.txt | xargs wget -c

5. 数据处理工具

awk

  • 用法
awk 条件类型1[操作1] 条件类型2[操作2] ... filename
  • 参数
-F fs or --field-separator fs
指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。
-v var=value or --asign var=value
赋值一个用户定义变量。
-f scripfile or --file scriptfile
从脚本文件中读取awk命令。
-mf nnn and -mr nnn
对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。
-W compact or --compat, -W traditional or --traditional
在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。
-W copyleft or --copyleft, -W copyright or --copyright
打印简短的版权信息。
-W help or --help, -W usage or --usage
打印全部awk选项和每个选项的简短说明。
-W lint or --lint
打印不能向传统unix平台移植的结构的警告。
-W lint-old or --lint-old
打印关于不能向传统unix平台移植的结构的警告。
-W posix
打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符**和**=不能代替^和^=;fflush无效。
-W re-interval or --re-inerval
允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。
-W source program-text or --source program-text
使用program-text作为源代码,可与-f命令混用。
-W version or --version
打印bug报告信息的版本。
  • 实例
zhangsan@node01:~$ last -n 5
zhangsan pts/1 192.168.149.1 Sat Oct 1 22:20 still logged in
zhangsan pts/1 192.168.149.1 Sat Oct 1 17:00 - 17:43 (00:43)
zhangsan pts/0 192.168.149.1 Sat Oct 1 17:00 - 17:10 (00:09)
zhangsan tty7 :0 Sat Oct 1 16:46 gone - no logout
zhangsan pts/1 192.168.149.1 Sat Oct 1 16:32 - 17:00 (00:27)

zhangsan@node01:~$ last -n 5 | awk print$1 "\\t" $3
zhangsan 192.168.149.1
zhangsan 192.168.149.1
zhangsan 192.168.149.1
zhangsan :0
zhangsan 192.168.149.1

6. sed工具

  • 用法
sed [-nefr] [操作]
  • 参数
-e<script>或--expression=<script> 以选项中指定的script来处理输入的文本文件。
-f<script文件>或--file=<script文件> 以选项中指定的script文件来处理输入的文本文件。
-h或--help 显示帮助。
-n或--quiet或--silent 仅显示script处理后的结果。
-V或--version 显示版本信息。
-r:sed的操作使用的是扩展型正则表达式的语法(默认是基础正则表达式语法)
  • 操作说明
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d :删除,因为是删除啊,所以 d 后面通常不接任何东东;
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正则表达式!例如 1,20s/old/new/g 就是啦!
  • 实例

1)​​查看文件内容​

zhangsan@node01:~$ cat f1.txt 
hello-world-coder
hello-hadoop-yarn
hive-spark-tez
mr-spark-impala
mr-flink-kafka
456
023
doris-kylin-presto
123
flume-kafka-flume
datax-sqoop

2)在 f1.txt 文件的第6行后添加一行,并将结果输出到标准输出,在命令行提示符下输入如下命令:

zhangsan@node01:~$ sed -e 6a\\newLine f1.txt 
hello-world-coder
hello-hadoop-yarn
hive-spark-tez
mr-spark-impala
mr-flink-kafka
456
newLine
023
doris-kylin-presto
123
flume-kafka-flume
datax-sqoop

3)​​以行为单位的新增/删除​​ 3.1)将 f1.txt 的内容列出并且列印行号,同时,请将第 2~5 行删除!

zhangsan@node01:~$ nl f1.txt | sed 2,5d
1 hello-world-coder
6 456
7 023
8 doris-kylin-presto
9 123
10 flume-kafka-flume
11 datax-sqoop

3.2)只要删除第 2 行

zhangsan@node01:~$ nl f1.txt | sed 2d 
1 hello-world-coder
3 hive-spark-tez
4 mr-spark-impala
5 mr-flink-kafka
6 456
7 023
8 doris-kylin-presto
9 123
10 flume-kafka-flume
11 datax-sqoop

3.3)删除第 3 到最后一行

zhangsan@node01:~$ nl f1.txt | sed 3,$d 
1 hello-world-coder
2 hello-hadoop-yarn

3.4)在第二行后(即加在第三行) 加上java coffee? 字样:

zhangsan@node01:~$ nl f1.txt | sed 2a java coffee
1 hello-world-coder
2 hello-hadoop-yarn
java coffee
3 hive-spark-tez
4 mr-spark-impala
5 mr-flink-kafka
6 456
7 023
8 doris-kylin-presto
9 123
10 flume-kafka-flume
11 datax-sqoop

3.5)增加两行以上

zhangsan@node01:~$ nl f1.txt | sed 2a java coffee or ......\\
> java coffee ?
1 hello-world-coder
2 hello-hadoop-yarn
java coffee or ......
java coffee ?
3 hive-spark-tez
4 mr-spark-impala
5 mr-flink-kafka
6 456
7 023
8 doris-kylin-presto
9 123
10 flume-kafka-flume
11 datax-sqoop

4)​​以行为单位的替换与显示​

4.1)将第 2-5 行的内容取代成为 No 2-5 number 呢?

$ nl testfile | sed 2,5c No 2-5 number
1 HELLO LINUX!
No 2-5 number
6 Taobao
7 Runoob
8 Tesetfile
9 Wiki

透过这个方法我们就能够将数据整行取代了。

4.2)仅列出 testfile 文件内的第 5-7 行:

$ nl testfile | sed -n 5,7p
5 Google
6 Taobao
7 Runoob

可以透过这个 sed 的以行为单位的显示功能, 就能够将某一个文件内的某些行号选择出来显示。

5)​​数据的搜寻并显示​

5.1)搜索 testfile 有 oo 关键字的行:

$ nl testfile | sed -n /oo/p
5 Google
7 Runoob

如果 root 找到,除了输出所有行,还会输出匹配行。

6)​​数据的搜寻并删除​

删除 testfile 所有包含 oo 的行,其他行输出

$ nl testfile | sed  /oo/d
1 HELLO LINUX!
2 Linux is a free unix-type opterating system.
3 This is a linux testfile!
4 Linux test
6 Taobao
8 Tesetfile
9 Wiki

7)​​数据的搜寻并执行命令​

搜索 testfile,找到 oo 对应的行,执行后面花括号中的一组命令,每个命令之间用分号分隔,这里把 oo 替换为 kk,再输出这行:

$ nl testfile | sed -n /oo/s/oo/kk/;p;q  
5 Gkkgle

最后的 q 是退出。

8)​​数据的查找与替换​

除了整行的处理模式之外, sed 还可以用行为单位进行部分数据的查找与替换<。

sed 的查找与替换的与 vi 命令类似,语法格式如下:

sed s/要被取代的字串/新的字串/g将 testfile 文件中每行第一次出现的 oo 用字符串 kk 替换,然后将该文件内容输出到标准输出:

sed -e s/oo/kk/ testfile

​g​​标识符表示全局查找替换,使 sed 对文件中所有符合的字符串都被替换,修改后内容会到标准输出,不会修改原文件:

sed -e s/oo/kk/g testfile

选项 ​​i​​ 使sed修改文件:

sed -i s/oo/kk/g testfile

批量操作当前目录下以​​test​​开头的文件:

sed -i s/oo/kk/g ./test* 接下来我们使用​​/sbin/ifconfig​​查询 IP:

$ /sbin/ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:90:CC:A6:34:84
inet addr:192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::290:ccff:fea6:3484/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
.....(以下省略).....

本机的 ip 是 192.168.1.100。

将 IP 前面的部分予以删除:

$ /sbin/ifconfig eth0 | grep inet addr | sed s/^.*addr://g
192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0

接下来则是删除后续的部分,即:

192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0。

将 IP 后面的部分予以删除:

$ /sbin/ifconfig eth0 | grep inet addr | sed s/^.*addr://g | sed s/Bcast.*$//g
192.168.1.100

​多点编辑​

一条​​sed​​命令,删除 testfile 第三行到末尾的数据,并把 HELLO 替换为 RUNOOB :

$ nl testfile | sed -e 3,$d -e s/HELLO/RUNOOB/
1 RUNOOB LINUX!
2 Linux is a free unix-type opterating system.

​-e 表示多点编辑​​,第一个编辑命令删除 testfile 第三行到末尾的数据,第二条命令搜索 HELLO 替换为 RUNOOB。

9)​​直接修改文件内容(危险动作)​

​sed​​可以直接修改文件的内容,不必使用管道命令或数据流重导向! 不过,由于这个动作会直接修改到原始的文件,所以请你千万不要随便拿系统配置来测试! 我们还是使用文件 regular_express.txt 文件来测试看看吧!

regular_express.txt 文件内容如下:

$ cat regular_express.txt 
runoob.
google.
taobao.
facebook.
zhihu-
weibo-

利用​​sed​​将 regular_express.txt 内每一行结尾若为 . 则换成 !

$ sed -i s/\\.$/\\!/g regular_express.txt
$ cat regular_express.txt
runoob!
google!
taobao!
facebook!
zhihu-
weibo-:q:q

利用​​sed​​直接在 regular_express.txt 最后一行加入 # This is a test:

$ sed -i $a # This is a test regular_express.txt
$ cat regular_express.txt
runoob!
google!
taobao!
facebook!
zhihu-
weibo-
# This is a test

由于​​$​​代表的是最后一行,而 a 的动作是新增,因此该文件最后新增 # This is a test!

sed 的 -i 选项可以直接修改文件内容,这功能非常有帮助!举例来说,如果你有一个 100 万行的文件,你要在第 100 行加某些文字,此时使用 vim 可能会疯掉!因为文件太大了!那怎办?就利用​​sed​​啊!透过​​sed​​直接修改/取代的功能,你甚至不需要使用 vim 去修订!

7. 参考

​https://www.runoob.com/linux/linux-command-manual.html​

管道显式 conda 列表

【中文标题】管道显式 conda 列表【英文标题】:Piping explicit conda list 【发布时间】:2016-11-10 13:16:36 【问题描述】:

我需要管道一些 conda 命令:

$ conda list --export | head -n 3
# This file may be used to create an environment using:
# $ conda create --name <env> --file <this file>
# platform: linux-64

这很好用。但是管道显式列表失败:

$ conda list --explicit | head -n 3
# This file may be used to create an environment using:
# $ conda create --name <env> --file <this file>
# platform: linux-64
An unexpected error has occurred.
Please consider posting the following information to the
conda GitHub issue tracker at:

    https://github.com/conda/conda/issues



Current conda install:

               platform : linux-64
          conda version : 4.2.12
       conda is private : False
      conda-env version : 4.2.12
    conda-build version : not installed
         python version : 2.7.12.final.0
       requests version : 2.11.1
       root environment : /home/me/miniconda3  (writable)
    default environment : /home/me/miniconda3
       envs directories : /home/me/miniconda3/envs
          package cache : /home/me/miniconda3/pkgs
           channel URLs : https://repo.continuum.io/pkgs/free/linux-64
                          https://repo.continuum.io/pkgs/free/noarch
                          https://repo.continuum.io/pkgs/pro/linux-64
                          https://repo.continuum.io/pkgs/pro/noarch
            config file : None
           offline mode : False



`$ /home/me/miniconda3/bin/conda list --explicit`

回溯是(对不起,它不允许我把它放在代码标签中......):

Traceback (most recent call last):    
File "/home/me/miniconda3/lib/python2.7/site-packages/conda/exceptions.py", line 479, in conda_exception_handler
return_value = func(*args, **kwargs)

File "/home/me/miniconda3/lib/python2.7/site-packages/conda/cli/main.py", line 145, in _main
  exit_code = args.func(args, p)

File "/home/me/miniconda3/lib/python2.7/site-packages/conda/cli/main_list.py", line 213, in execute
  print_explicit(prefix, args.md5)

File "/home/me/miniconda3/lib/python2.7/site-packages/conda/cli/main_list.py", line 190, in print_explicit
  print(url + ('#%s' % md5 if add_md5 and md5 else ''))

IOError: [Errno 32] Broken pipe

这可能是一个错误吧?没有管道它工作正常。

【问题讨论】:

我无法在使用 Python 3 的 Ubuntu 16.04 系统上重现此问题。您使用的是什么操作系统? 我在 mac osx 上试过这个。我会尝试使用 linux 但是您的conda info 显示linux-64? FWIW,我也无法在 OS X 上重现它,但同样,它的 Miniconda 3 对不起,我弄错了。你是对的,我在 Linux 上执行了命令。然后我使用这些信息在 mac 上安装 conda 包,这就是我感到困惑的原因。 【参考方案1】:

出现损坏的管道是因为head 在收到指示显示的 3 行后正在关闭输出流。你会注意到你在输出中得到了这三行。下次 conda 尝试打印时,它无法打印,因为 head 已关闭管道。这就是导致此异常的原因。这不是 conda 的问题。在此处查看有关 python 中损坏的管道异常的更多信息:IOError: [Errno 32] Broken pipe: Python

现在有一个潜在的解决方法:

$ conda list --explicit &gt; /tmp/conda-explicit-output &amp;&amp; head -n 15 /tmp/conda-explicit-output &amp;&amp; rm /tmp/conda-explicit-output

是的,它很丑,但它可能会完成工作。

【讨论】:

我猜你解决了!所以一般来说这不是管道问题。如果我这样做$ conda list --explicit | wc -l,我会得到297。所以现在:$ conda list --explicit | head -n 297 返回正确的结果。实际上我使用head 进行测试,我本身并不需要它。所以我不需要“丑陋”的代码;)谢谢!

以上是关于Linux好用的管道命令的主要内容,如果未能解决你的问题,请参考以下文章

linux之tree命令

Linux基础命令—tree

Linux特殊符号浅谈

Linux 管道

如何从管道 linux 命令连续将输出发送到文件? [复制]

Linux命令~type,file,stat的区别