Linux:管线命令
http://blog.csdn.net/pipisorry/article/details/39760961当Linux执行一个程序的时候,会自动打开三个流,标准输入(standard input),标准输出(standard output),标准错误(standard error)。比如说你打开命令行的时候,默认情况下,命令行的标准输入连接到键盘,标准输出和标准错误都连接到屏幕。<...
http://blog.csdn.net/pipisorry/article/details/39760961
当Linux执行一个程序的时候,会自动打开三个流,标准输入(standard input),标准输出(standard output),标准错误(standard error)。比如说你打开命令行的时候,默认情况下,命令行的标准输入连接到键盘,标准输出和标准错误都连接到屏幕。
<符号改变标准输入
比如cat命令,它可以从标准输入读入文本流,并输出到标准输出:
$cat < a.txt
我们将cat标准输入指向a.txt,文本会从文件流到cat,然后再输出到屏幕上。
同时重新定向标准输出
$cat < a.txt > b.txt
使用2>& 1或者>&来同时重新定向标准输出和标准错误
somecmd >> all_result 2>& 1
somecmd &> all_result #这种方式不能追加
如果只想重新定向标准错误,可以使用2>。
管线命令 (pipe)
管线命令在 bash 的连续的处理程序中是相当重要的,在 log file 的分析当中也是相当重要的一环。
Note: 管线命令前面命令的输出可以使用{}收集。
撷取命令: cut, grep
排序命令: sort, uniq, wc
双向重导向: tee
字符转换命令: tr, col, join, paste, expand
分割命令: split
参数代换: xargs
关于减号 - 的用途
撷取命令: cut, grep
linux cut命令
$ cut -d'分隔字符' -f fields
$ cut -c 字符区间
选项与参数:
-d :后面接分隔字符。与 -f 一起使用;
-f :依据 -d 的分隔字符将一段讯息分区成为数段,用 -f 取出第几段的意思;
-c :以字符 (characters) 为单位取出固定字符区间;即取字符串取的子串
示例:
只取前3位字符
echo 1234567 | cut -c -3 #123
取3位之后的字符,即去除前2位字符
echo 1234567 | cut -c 3- #34567
取第3位字符
echo 1234567 | cut -c 3 #3
linux grep命令
grep是一种强大的文本搜索工具,全称是Global Regular Expression Print,表示全局正则表达式版本。它能使用正则表达式搜索文本,并把匹 配的行打印出来。
命令格式
$ grep [-acinv] [--color=auto] '搜寻字串' filename
选项与参数:
-a :将 binary 文件以 text 文件的方式搜寻数据
-c :计算找到 '搜寻字串' 的次数,只输出匹配行的计数
-i :忽略大小写的不同,所以大小写视为相同(只适用于单字符)
-n :顺便输出行号,显示匹配行及行号。
-v :反向选择,亦即显示出没有 '搜寻字串' 内容的那一行!
--color=auto :可以将找到的关键字部分加上颜色的显示喔!
-h :查询多文件时不显示文件名。
-l :查询多文件时只输出包含匹配字符的文件名。
-s :不显示不存在或无匹配文本的错误信息。
-E : 扩展选项为正则表达式。 表示'搜寻字串'是正则表达式。
filename 搜索全部文件的话用 *
pattern正则表达式主要参数:
\: 忽略正则表达式中特殊字符的原有含义。
^:匹配正则表达式的开始行。
$: 匹配正则表达式的结束行。
\<:从匹配正则表达式的行开始。
\>:到匹配正则表达式的行结束。
\< 和 \> 分别标注单词的开始与结尾。例如:
grep man * 会匹配 ‘Batman’、’manic’、’man’等,
grep ‘\<man’ * 匹配’manic’和’man’,但不是’Batman’,
grep ‘\<man\>’ 只匹配’man’,而不是’Batman’或’manic’等其他的字符串。[ ]:单个字符,如[A]即A符合要求 。
[ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求 。
。:所有的单个字符。应该是英文句号?
* :有字符,长度可以为0。
示例
grep 'test' d* 显示所有以d开头的文件中包含 test的行。
cat d | grep 'test' 作为管线命令时
grep 'test' aa bb cc 显示在aa,bb,cc文件中匹配test的行。
grep -l pattern files :只列出匹配的文件名,
grep -L pattern files :列出不匹配的文件名,
grep -w pattern files :只匹配整个单词,而不是一部分(如匹配’magic’,而不是’magical’),
grep -C number pattern files :匹配的上下文分别显示[number]行
目录下搜索带字符 串’magic’的文件:
$ grep magic /usr/src/Linux/Doc/*
sysrq.txt:* How do I enable the magic SysRQ key?
sysrq.txt:* How do I use the magic SysRQ key?
其中文件’sysrp.txt’包含该字符串。默认情况下,’grep’只搜索当前目录。如果 此目录下有许多子目录,’grep’会以如下形式列出:grep: sound: Is a directory。这可能会使’grep’ 的输出难于阅读。这里有两种解决的办法:
明确要求搜索子目录:grep -r
或忽略子目录:grep -d skip
正则匹配
如果用egrep或grep -E,就不用”\”号进行转义。
grep -E "858|17430|20517|180" texfile
不加-E时的正则匹配,一般都要加\
grep "858\|17430\|20517\|180" texfile
grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行,
grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。
grep ‘[a-z]\{5\}’ aa 显示所有包含每个字符串至少有5个连续小写字符的字符串的行。
grep ‘w\(es\)t.*\1′ aa 如果west被匹配,则es就被存储到内存中,并标记为1,然后搜索任意个字符(.*),这些字符后面紧跟着 另外一个es(\1),找到就显示该行。-E可直接写成’w(es)t.*\1′。
grep字符串搜索算法
grep速度快的一个重要原因是使用了Boyer-Moore算法作为字符串搜索算法
grep之字符串搜索算法Boyer-Moore由浅入深(比KMP快3-5倍)
排序命令: sort, uniq, wc
linux sort命令
排序的字符与语系的编码有关,因此, 如果您需要排序时,建议使用 LANG=C 来让语系统一,数据排序比较好一些。
$ sort [-fbMnrtuk] [file or stdin]
选项与参数:
-f :忽略大小写的差异,例如 A 与 a 视为编码相同;
-b :忽略最前面的空白字符部分;
-M :以月份的名字来排序,例如 JAN, DEC 等等的排序方法;
-n :使用“纯数字”进行排序(默认是以文字体态来排序的);
-r :反向排序;
-u :就是 uniq ,相同的数据中,仅出现一行代表;
-t :分隔符号,默认是用 [tab] 键来分隔;
-k :以那个区间 (field) 来进行排序的意思
linux uniq命令
将重复的数据仅列出一个显示
[dmtsai@study ~]$ uniq [-ic]
选项与参数:
-i :忽略大小写字符的不同;
-c :进行计数
Note: 特别要注意的地方: 'uniq' does not detect repeated lines unless they are adjacent. You may want to sort the input first, or use 'sort -u' without 'uniq'. Also, comparisons honor the rules specified by 'LC_COLLATE'.
也就是在使用uniq之前要进行排序,否则相隔的相同字符不会去重。这样的话,直接使用sort -nu最好了。
pipi@pipicmp:~/files/DATASETS/tianchi/ccf_data_revised$ cat ccf_online_stage1_train.csv | cut -d ',' -f 2 | uniq | sort -n | head
10001
10001
10001...
10001
pipi@pipicmp:~/files/DATASETS/tianchi/ccf_data_revised$ cat ccf_online_stage1_train.csv | cut -d ',' -f 2 | sort -n | uniq | head
10001
10002
10003
10004...
10009
10010
linux wc命令
要知道文件里面有多少字?多少行?多少字符?
$ wc [-lwm]
选项与参数:
-l :仅列出行;
-w :仅列出多少字(英文单字);
-m :多少字符;
统计项目中的代码行数cloc
cloc能够统计包括:代码行数、注释、空行、文件大小等数据。另外,还支持对软件开发项目的各个开发阶段的工数、成本、质量指标等进行分析和预测。
$ sudo apt-get install cloc
SocialNetworks$ cloc .
[cloc网站]
直接写简单的可以这样:
find . \( -path ./tmp_data -o -path ./gowalla-exp \) -prune -o \( -name '*.pyc' -o -name '*.py' -type f \) -print | xargs -0 cat | grep -v -e ^$ -e ^\s*\#.*$ | wc -l | more
字符转换命令: tr, col, join, paste, expand
tr
tr 可以用来删除一段讯息当中的文字,或者是进行文字讯息的替换!
$ tr [-ds] SET1 ...
选项与参数:
-d :删除讯息当中的 SET1 这个字串;
-s :取代掉重复的字符!
范例一:将 last 输出的讯息中,所有的小写变成大写字符:
$ last tr '[a-z]' '[A-Z]'
# 事实上,没有加上单引号也是可以执行的,如:“ last | tr [a-z] [A-Z] ”
范例二:将 /etc/passwd 输出的讯息中,将冒号 (:) 删除
$ cat /etc/passwd | tr -d ':'
范例三:将 /etc/passwd 转存成 dos 断行到 /root/passwd 中,再将 ^M 符号删除
$ cp /etc/passwd ~/passwd && unix2dos ~/passwd
$ file /etc/passwd ~/passwd
/etc/passwd: ASCII text
/home/dmtsai/passwd: ASCII text, with CRLF line terminators <==就是 DOS 断行
$ cat ~/passwd | tr -d '\r' > ~/passwd.linux
# 那个 \r 指的是 DOS 的断行字符,关于更多的字符,请参考 man tr
$ ll /etc/passwd ~/passwd*
-rw-r--r--. 1 root root 2092 Jun 17 00:20 /etc/passwd
-rw-r--r--. 1 dmtsai dmtsai 2133 Jul 9 22:13 /home/dmtsai/passwd
-rw-rw-r--. 1 dmtsai dmtsai 2092 Jul 9 22:13 /home/dmtsai/passwd.linux
# 处理过后,发现文件大小与原本的 /etc/passwd 就一致了!
其实这个指令也可以写在“正则表达式”里头!因为他也是由正则表达式的方式来取代数据的! 以上面的例子来说,使用 [] 可以设置一串字呢!也常常用来取代文件中的怪异符号! 例如上面第三个例子当中,可以去除 DOS 文件留下来的 ^M 这个断行的符号!这东西相当的有用!相信处理 Linux & Windows 系统中的人们最麻烦的一件事就是这个事情啦!亦即是 DOS 下面会自动的在每行行尾加入 ^M 这个断行符号!这个时候除了以前讲过的 dos2unix 之外,我们也可以使用这个 tr 来将 ^M 去除! ^M 可以使用 \r 来代替之!
join
join 看字面上的意义 (加入/参加) 就可以知道,他是在处理两个文件之间的数据, 而且,主要是在处理“两个文件当中,有 "相同数据" 的那一行,才将他加在一起”的意思。
paste
linux中按列合并文件的命令。相对于 join 必须要比对两个文件的数据相关性, paste 就直接“将两行贴在一起,且中间以 [tab] 键隔开”而已!简单的使用方法:
$ paste [-d] file1 file2
选项与参数:
-d :后面可以接分隔字符。默认是以 [tab] 来分隔的!
- :如果 file 部分写成 - ,表示来自 standard input 的数据的意思。
expand
将 [tab] 按键转成空白键$ expand [-t] file
选项与参数:
-t :后面可以接数字。一般来说,一个 tab 按键可以用 8 个空白键取代。也可以自行定义一个 [tab] 按键代表多少个字符呢!
分区命令: split
split 可以帮你将一个大文件,依据文件大小或行数来分区,就可以将大文件分区成为小文件了!
在 Linux 下面要将文件分区的话,那么就使用 -b size 来将一个分区的文件限制其大小,如果是行数的话,那么就使用 -l line 来分区!
$ split [-bl] file PREFIX
选项与参数:
-b :后面可接欲分区成的文件大小,可加单位,例如 b, k, m 等;
-l :以行数来进行分区。
PREFIX :代表前置字符的意思,可作为分区文件的前导文字。
范例一:我的 /etc/services 有六百多K,若想要分成 300K 一个文件时?
split -b 300k /etc/services services
ll -k services*
-rw-rw-r--. 1 dmtsai dmtsai 307200 Jul 9 22:52 servicesaa
-rw-rw-r--. 1 dmtsai dmtsai 307200 Jul 9 22:52 servicesab
-rw-rw-r--. 1 dmtsai dmtsai 55893 Jul 9 22:52 servicesac
# 只要写上前导文字,小文件就会以 xxxaa, xxxab, xxxac 等方式来创建小文件的!
范例二:如何将上面的三个小文件合成一个文件,文件名为 servicesback
cat services* >> servicesback
# 用数据流重导向就好
范例三:使用 ls -al / 输出的信息中,每十行记录成一个文件
$ ls -al / | split -l 10 - lsroot
$ wc -l lsroot*
10 lsrootaa
10 lsrootab
4 lsrootac
24 total
# 如果需要 stdout/stdin 时,但偏偏又没有文件,# 有的只是 - 时,那么那个 - 就会被当成 stdin 或 stdout
示例1:
mkdir data
split -l 5000 data.csv data/data_
# 或者 split -b 900k data.csv data/data_ # 这个中文有编码问题(可能是刚好一个中文被切成了两半),另外就是最后一行的句子一般都会被切到两个文件中。所以可以先用-b切试试看,再打开文件看下多少行,再用-l行来切。
ls data/
data_aa data_ab data_ac data_ad
示例2:
split -b 50k a -d -a 4 data/a_
split -b 1G a -d -a 4 data/a_
将数据a分成50k大小的小文件,存入的文件夹data中,文件名的前缀为a_,系数不是字母而是数字(-d),后缀系数为四位数(-a 4)。结果就是a_0001,...这种。
示例2:split -l 2482 a -d -a 4 data/a_
通过行数来分
Note: 可以先通过wc -l a 读出文件一共有多少行;或者通过du -h a读出文件多大;再决定怎么分。
参数代换: xargs
{非管道命令变成管道命令!}
以字面上的意义来看, x 是加减乘除的乘号,args 则是 arguments (参数) 的意思,所以就是在产生某个指令的参数的意思! xargs 可以读入 stdin 的数据,并且以空白字符或断行字符作为分辨,将 stdin 的数据分隔成为 arguments 。 因为是以空白字符作为分隔,所以,如果有一些文件名或者是其他意义的名词内含有空白字符的时候, xargs 可能就会误判了~
$ xargs [-0epn] command
选项与参数:
-0 :如果输入的 stdin 含有特殊字符,例如 `, \, 空白键等等字符时,这个 -0 参数可以将他还原成一般字符。这个参数可以用于特殊状态喔!If there are blank spaces or characters (including newlines) many commands will not work. This option take cares of file names with blank space.-e :这个是 EOF (end of file) 的意思。后面可以接一个字串,当 xargs 分析到这个字串时,就会停止继续工作!
-p :在执行每个指令的 argument 时,都会询问使用者的意思;
-n :后面接次数,每次 command 指令执行时,要使用几个参数的意思。
-I :指定了管道前命令作为参数所应该在管道后面命令的位置。e.g. | xargs -I _ mv _ /tmp/c). Replace occurrences of replace-str in the initial-arguments with names read from standard input. Also, unquoted blanks do not terminate input items; instead the separator is the newline character.当 xargs 后面没有接任何的指令时,默认是以 echo 来进行输出!
示例
$somecmd | xargs -I {} mv {} ~/tmp
$ find /usr/sbin -perm /7000 | xargs ls -l
$ find . -name "*.bak" -print0 | xargs -0 -I {} mv {} ~/old.files
出错:xargs: cat: terminated by signal 13
find . \( -name '*.pyc' -o -name '*.py' -type f \) -print | xargs cat
原因:
可能的解决:
修改成find . -type f -exec grep "something" {} \; -quit
This is how it works:The -exec will work when the -type f will be true. And because grep returns 0 (success/true) when the -exec grep "something" has a match, the -quit will be triggered.
[bash find xargs grep only single occurence]
减号 - 的用途
在管线命令当中,常常会使用到前一个指令的 stdout 作为这次的 stdin , 某些指令需要用到文件名称 (例如 tar) 来进行处理时,该 stdin 与 stdout 可以利用减号 "-" 来替代, 举例来说:
mkdir /tmp/homeback
tar -cvf - /home | tar -xvf - -C /tmp/homeback
上面这个例子是说:“我将 /home 里面的文件给他打包,但打包的数据不是纪录到文件,而是传送到 stdout; 经过管线后,将 tar -cvf - /home 传送给后面的 tar -xvf - ”。后面的这个 - 则是取用前一个指令的 stdout, 因此,我们就不需要使用 filename 了!
ref: 鸟哥的linux私房菜
更多推荐
所有评论(0)