cut 命令在Linux和Unix中的作用是从文件中的每一行中截取出一些部分,并输出到标准输出中。我们可以使用 cut 命令从一行字符串中于以字节,字符,字段(分隔符)等单位截取一部分内容出来。 在本文中,我们通过一些例子来了解 cut 命令的使用,这些使用方法在我们的日常工作中也是非常常用的。
4 Z: J$ x2 ?% U# q# f. s$ {
Cut 命令和语法
5 R: V0 r2 j: L$ K @( U6 h( T x; ?' I3 `0 S9 O- O0 l/ k
cut 命令的基本语法如下: - <font color="black">" {3 R2 }) k) F/ ^ D
- $ cut OPTION... [FILE]...</font>
复制代码
" e2 I7 \1 d5 B! ~
我们先来了解一下 cut 的一些选项,cut 命令必须要指定选项才能执行。 -f : 提取指定的字段,cut 命令使用 Tab 作为默认的分隔符。 -d : Tab 是默认的分隔符,使用这一选项可以指定自己的分隔符。 -b : 提取指定的字节,也可以指定一个范围。 -c : 提取指定的字符,可以是以逗号分隔的数字的列表,也可以是以连字符分隔的数字的范围。 –complement : 补充选中的部分,即反选。 –output-delimiter : 修改输出时使用的分隔符。 --only-delimited : 不输出不包含分隔符的列。 我们以如下的名为 context.txt 的文本文件和 /etc/passwd 文件来为例来进行说明。 - ( H' r$ G0 Z1 K$ N2 r
- $ cat content.txt
+ B6 y0 o9 J- Q; p5 |8 [2 e - Ubuntu Linux
* a! B3 ] a: J! C - Microsoft Windows
' g6 ]# ?% \1 ] ^7 ^/ z3 I - OsX El Capitan
# ~/ d$ J6 T5 D# @ - Unix9 t0 d8 W" A$ d, r( }1 a- `3 ?7 r
- FreeBSD
复制代码
, b7 ?4 I5 m V# K
如何指定分隔符
3 v5 ]( f- b7 ~) d
: J( D, N& r9 z0 H4 X# T3 z; \7 X
最常用的选项是 -d 和 -f 的组合,这会根据 -d 指定的分隔符和 -f 列出的字段来提取内容。 例如在这个例子中只打印出 /etc/passwd 文件每一行的第一个字段,用的分隔符是 : - <font color="black">) h3 N. ~, a0 n' I& _% L, Q
- $ cut -d':' -f1 /etc/passwd; d, h+ k4 z' f3 y1 y& _
- root
# o' t# G, S+ @" n - bin6 f, P' ~5 R0 D4 c. h# a
- daemon
1 d# B- U3 v) z - adm6 h" E. r8 \% i) n3 r
- lp, r4 @1 v( e3 o# J
- sync4 R7 f b) }* F# Z4 T8 ]* a
- shutdown
" G( t$ B6 a# x1 i8 E2 a4 J# }2 S - halt
6 p3 L+ p# C/ z: z( e# T8 }8 a - mail
& E1 C: N4 \ C, D7 K2 ^% A% K - operator! n7 Y4 O5 b/ I7 u6 O* }
- games0 P! H8 L% A" U- p, o; Y
- alvin* G$ o1 p7 [$ V0 [/ P$ @7 [
- liangxu. c) `" `! F3 m# q$ Q5 B) X
- ...</font>
复制代码
* Z! `1 f: F0 s1 v3 W) Y c
在下面这个例子中我们用空格作为分隔符打印 content.txt 文件的第一个字段 - <font color="black">+ A" R6 i, v2 c1 _1 ~4 e( Z R7 i0 |) H
- $ cut -d " " -f 1 content.txt 3 G8 w4 B+ T& p0 \4 G* H
- Ubuntu
& [* i0 S( E- v" Z! B - Microsoft
, S" z% [' b3 b& U2 q( N - OsX
0 R0 s4 r5 |/ W7 D/ B - Unix5 X) K/ J0 C4 Q& E; D' \
- FreeBSD</font>
复制代码; z- ~% i# n( W
在下面这个例子中我们提取了多个字段。这里,我们使用冒号(:)分隔符从文件 /etc/passwd 中包含字符串 /bin/bash 的行提取第一和第六个字段。 - <font color="black">
. F. }3 ~, ]: R p0 m$ g) X - $ grep "/bin/bash" /etc/passwd | cut -d':' -f1,6
( o5 @0 ^7 `8 b. j% p8 |5 c - root:/root
' b* K( E. B/ O7 T. y2 X5 M8 q - alvin:/home/alvin</font>
复制代码6 ?- R/ r' b( z# O( O7 M* a
要显示字段的某个范围,可以指定开始和结束的字段,中间用连字符(-)连接,如下所示: - <font color="black">
: c+ S% P6 T5 H, ?7 Y# l( O - $ grep "/bin/bash" /etc/passwd | cut -d':' -f1-4,6,7
2 A/ i3 U: a& E& N+ C - root:x:0:0:/root:/bin/bash
, H& k( z. @8 @% v% c - alvin:x:1000:1000:/home/alvin:/bin/bash</font>
复制代码
t3 s& i) F! E9 o% L: D
& j$ D( b+ e7 C: j
如何补全选择的输出
/ z( ]9 T' w# n- u1 k O- G7 g% k9 L3 X' I1 F& a$ ?' s, S9 A( Q! Q
要补全选择输出的字段(即反选),使用 --complement 选项。这一选项输出所有的字段,除了指定的字段。 在下面这个例子中输出 /etc/passwd 文件中包含 /bin/bash 的行中除了第二个字段以外的所有字段: - <font color="black">
, g# {# a6 U5 e% F. s - $ grep "/bin/bash" /etc/passwd | cut -d':' --complement -f2
; s( E0 L z, K# F3 u - root:0:0:root:/root:/bin/bash</font>
复制代码
0 S1 ^( ~( @3 b5 T
( ], _' ^4 i) P- \
如何指定输出的分隔符 & b& n2 \3 K$ r/ O" f
4 Q! f; F) d* b U$ @) C8 d" P
使用 --output-delimiter 可以指定输出的分隔符。输入的分隔符由 -d 来指定,而输出分隔符和输入分隔符默认是一样的。 我们先以下面的例子来测试不指定输出分隔符时的输出; - <font color="black">
1 d! x+ t) s; @$ B( B( e - $ cut -d: -f1,7 /etc/passwd | sort | uniq -u
7 s7 w0 g$ E: b: e/ L( d! c6 { - _apt:/usr/sbin/nologin/ O% ?$ `0 C- k8 u
- backup:/usr/sbin/nologin2 [4 \9 m( Q$ K' c' G2 B% v
- bin:/usr/sbin/nologin
* S2 R# J9 Z, l' q) q% f - daemon:/usr/sbin/nologin8 q: M, R, }9 @5 f9 O& y* d
- dnsmasq:/usr/sbin/nologin5 r; s/ r" q8 o$ v2 @
- games:/usr/sbin/nologin: O' I( c) u. y2 k$ s# i' s# N. |) B
- gnats:/usr/sbin/nologin
; s2 L; b9 [1 W) d. Y - irc:/usr/sbin/nologin
: o( y: i g+ a1 o, t" X1 G - landscape:/usr/sbin/nologin+ [7 |4 M' ]1 R' W, o2 r
- list:/usr/sbin/nologin/ m. }$ h9 `2 k# w1 {, a
- lp:/usr/sbin/nologin
0 O& K& V$ W( a( D, ]6 }$ t: @ - lxd:/bin/false</font>
复制代码9 R# N/ |5 s& c
现在我们加上--output-delimiter选项,将输出分隔符指定为空格: - <font color="black">
0 b& Q6 c5 k$ {: ~6 q: o& X. O% J6 R - $ cut -d: -f1,7 --output-delimiter ' ' /etc/passwd | sort | uniq -u3 z1 z6 w9 ]) T1 ? L2 i' q5 ]% P
- _apt /usr/sbin/nologin' u0 q5 E8 C3 |! b2 u8 \
- backup /usr/sbin/nologin
% _, y2 {. J. K' j- Q3 p - bin /usr/sbin/nologin, R, I- k; Q+ k1 ?, m
- daemon /usr/sbin/nologin3 p+ c8 l! f# }
- dnsmasq /usr/sbin/nologin, v) A& M; X: d) ?6 V6 @
- games /usr/sbin/nologin
3 J7 Z& W7 X1 Y( Y& E - gnats /usr/sbin/nologin
1 s- |( E6 J4 n - irc /usr/sbin/nologin9 Y6 w. Y# [' i$ `
- landscape /usr/sbin/nologin
/ p2 Y, I/ l& f G& c: B - list /usr/sbin/nologin
- D* { n2 A) ? - lp /usr/sbin/nologin8 `! _3 c: {( {7 A+ o
- lxd /bin/false</font>
复制代码# y( D7 T- L9 e
我们再测试一个例子,用分隔符让每一行打印一个字段。 我们将 --output-delimiter 指定为 $'\n' 表换行。 输出结果为: - 6 e% t0 N& O3 _& B' g
- $ grep root /etc/passwd | cut -d':' -f1,6,7 --output-delimiter=[/color][/font][/backcolor][p=26, null, left][backcolor=rgb(255, 255, 255)][font=Tahoma][color=black]1 S; u- \4 `0 _) T9 C' |+ m
- [/color][/font][/backcolor]
: {% u& k- K. {0 W; G9 i - [/p][align=left][backcolor=rgb(255, 255, 255)]/ n9 I, u+ X" B( o I# T6 E
- [/backcolor][/align][p=23, null, left][font=Tahoma][color=black]如何以字符的方式提取内容[/color][/font][/p]
$ o9 I9 F3 P0 ^: J" ` - [align=left][backcolor=rgb(255, 255, 255)]' k9 A5 P3 O$ w5 \
- [/backcolor][/align][p=26, null, left][backcolor=rgb(255, 255, 255)][font=Tahoma][color=black]-c选项可以用来根据字符位置进行提取,注意空格和Tab也以字符来处理。[/color][/font][/backcolor][/p][p=26, null, left][backcolor=rgb(255, 255, 255)][font=Tahoma][color=black]打印 context.txt 文件每一行的第一个字符,如下:[/color][/font][/backcolor][/p][code]<font style="background-color:rgb(255, 255, 255)"><font color="black" face="Tahoma">' p. i4 f" f% }* r! T
- $ cut -c 1 content.txt& N# K# s T; ^1 n3 b$ g0 `. I
- U
. @2 m* S2 W5 w/ l% h& s0 s - M) j Y/ v8 V8 m6 f0 Z
- O
6 l1 X7 Q3 }& S8 D3 S( n0 {, O - U
/ U8 q8 _3 ]9 H) Y+ _, ^% s - F</font></font>
. m. ?& b, b6 g t
复制代码下面显示了 context.txt 文件每一行的第一至七个字符; - * D, T2 j; W2 a0 i/ k
- $ cut -c 1-7 content.txt
% I- [- w" Z% Q: |/ A3 P; J1 }& D - Ubuntu
0 D" M- [ n' ]% Z s* n4 z6 A - Microso7 z/ `+ W' D7 W; {6 q! M2 p3 Z7 q: j
- OsX El
1 R5 [- z& i# G$ M - Unix
7 g; I8 S0 j( o/ M - FreeBSD
复制代码
* k8 Z7 p0 k8 v
我们再测试一下只指定开始或结束的位置。 下面提取第二个到最后一个字符: - <font color="black">* u" w8 W, `4 H0 ]2 ~2 z
- $ cut -c2- content.txt( ?: ?9 V( o( f$ P( l8 _
- buntu Linux
0 v# `7 ~# k% b- T5 k6 _% k6 r- g+ Q - icrosoft Windows
) K$ `1 x( g- E - sX El Capitan3 E* V( m9 G$ I3 P! v& q
- nix
$ c/ W+ X: s# _9 i$ n - reeBSD</font>
复制代码3 n: Z0 y8 {) j
提取第一到第四个字符: - / s( k: _9 G0 b/ Z, s
- cut -c-4 content.txt, P" e8 i# |3 a5 s5 C3 z
- Ubun
- z1 L% M8 }7 O - Micr7 F3 e6 T, z5 Q; J. d
- OsX1 c- b9 j& R) C% N+ ], s! Q0 A9 N, J
- Unix# [/ V3 b8 k4 ?8 v* E/ r
- Free
复制代码
- l9 \) c% K! x3 `. t
* a. ^6 U3 ?/ t/ ~) K
$ y" [! T2 p0 Q# f
如何根据字节提取
7 s7 g7 K& l3 }) N6 S. ]
9 S `" P u; E$ z8 B! e
使用-b选项通过指定字节的位置来选择一行的某一部分,使用逗号分隔每个指定位置,或用连字符 - 指定一个范围。 下面这个例子提取 content.txt 文件每一行的第一,二,三个字节: - <font color="black">( I3 n0 Y/ a9 C/ @! U
- $ cut -b 1,2,3 content.txt . O8 Q2 V* }$ {! d5 h% U0 s$ E
- Ubu
; o5 M7 R1 ?4 [2 D6 | - Mic7 x3 ]$ S5 p# m% R
- OsX) P8 `' G8 f* a6 J+ P
- Uni" n" L& x$ `3 J f
- Fre</font>
复制代码+ Q+ m2 Q& A$ _, r' d* {: G8 M
我们也可以用如下命令列出一个范围; - <font color="black">% O! ?: [, f* t' D5 }
- $ cut -b 1-3,5-7 content.txt 5 C, B9 X2 m* s$ \, P) T z( r" H3 z
- Ubutu " `# ^4 O; T5 b# a+ G1 i ~
- Micoso
3 s- N2 g v- Z6 ^$ Y - OsXEl % i' w/ I& U( e( ?
- Uni8 D0 v; M0 w4 S# S7 `5 k
- FreBSD</font>
复制代码. u& `0 a% R+ j, I- @$ P
# W# h6 W7 s3 I! U) U
一些实用的例子 + l3 m& U' @* z) Z0 A( T
3 B1 i ~+ \3 s. ~' K% P' L
cut 是一个实用的命令,常常和其他Linux或Unix命令结合使用 。 例如如果你想提取 ps 命令中的 USER,PID和COMMAND: - <font color="black">3 K" [5 e$ q" t. [5 n& ~0 a' L0 I+ H
- ps -L u n | tr -s " " | cut -d " " -f 2,3,14-
* T: m2 p h# B& O& ]4 U" \ - USER PID COMMAND0 s" ^4 {$ C9 L0 @3 C
- 0 676 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyS0 vt220
! c- G, Z6 a Y. w4 W/ p* \ - 0 681 /sbin/agetty -o -p -- \u --noclear tty1 linux
* |" C" ?0 b$ G, B3 e( o* X - 0 23174 -bash
- Y M$ e1 W" H0 j2 J, u - 0 26737 ps -L u n) B; Q' h8 Y( d9 g3 i: x* x
- 0 26738 tr -s, ^; a" f# [1 S- J$ f
- 0 26739 cut -d -f 2,3,14-</font>
复制代码
3 M% f7 B( S) i* `) w7 i2 i7 g3 n3 [
再测试一个例子,提取内存的 total,used和free值,并保存到一个文件中。 - <font color="black">) Z* g5 q) a s h4 g: I& _0 W
- $ free -m | tr -s ' ' | sed '/^Mem/!d' | cut -d" " -f2-4 >> memory.txt
# I& u/ \/ \. _7 s - $ cat memory.txt$ u( O- t- F! `3 _7 B
- 985 86 234</font>
复制代码
' ]' q- ]" {! d( u1 b4 j
0 a* z4 G* D$ N0 Q1 K2 c% n" `
总结
, Y7 J. t/ Y& J- l7 W: |2 H, a3 `
1 |2 H! I7 X+ R) H- L9 w5 O9 x
cut 命令可以和很多其他Linux或Unix命令通过管道连接。可以通过管道传递一个或多个过滤器进行额外的文本处理。 cut 命令的局限性之一是它不支持指定多个字符作为分隔符。多个空格会被计算为多个字段分隔符,因此必须在 cut 命令前使用 tr 命令才能获得需要的输出。 U+ T4 `) |' e; |- w: l
\n'! f- P, K: @% E" t+ P3 F4 ?6 E1 G
root, u6 O, x. q; Q8 W& w$ e4 q( @
/root
4 q' p% x, ~) l1 B) ~) u: G" k/bin/bash
3 z9 Q: Y. x5 {1 D- g! Eoperator
& `% E' i3 F: N; s/ n k* P" M/root: G" E2 ]& K. c
/sbin/nologin[/code]) r- G" \" X' X: {
7 Y2 W5 }. O4 i. z& w& R% O 7 m) p# \; d6 i" r& Q. D2 h
如何以字符的方式提取内容
0 e8 _/ ~. O7 @% e3 c+ _& J0 s! ?
& a. I- r1 \, G& T+ p7 j& X+ `
-c选项可以用来根据字符位置进行提取,注意空格和Tab也以字符来处理。 打印 context.txt 文件每一行的第一个字符,如下: - <font style="background-color:rgb(255, 255, 255)"><font color="black" face="Tahoma">- x+ v+ v: }+ D# S, X/ q) P
- $ cut -c 1 content.txt9 ?4 s: ]. x7 a) `9 B* G
- U9 P' a* D" @$ I* R! W5 j
- M
. m9 Z. C3 h) [4 o - O
8 \9 _6 I1 ]+ J7 M/ z; i, J* B - U
( \' w+ G, F9 [. ^ - F</font></font>
5 x, Z0 x& j7 n8 i
复制代码下面显示了 context.txt 文件每一行的第一至七个字符;
0 N2 x& j P" b9 J5 a- $ cut -c 1-7 content.txt% Q' m, x& M8 p: Z, F! A% d, y8 s
- Ubuntu+ A. L$ R# t& v) E7 q9 s6 R
- Microso
. r. ^3 Y' Y- V( Z3 y0 U - OsX El
; y5 Q7 E& Q; G; I1 l4 e3 O - Unix# j1 I1 b# W7 b% S$ o
- FreeBSD
复制代码& y/ R+ V- H: \1 w/ B& I5 z. e! K4 N
我们再测试一下只指定开始或结束的位置。 下面提取第二个到最后一个字符: - <font color="black">1 m7 E. e* ~/ J
- $ cut -c2- content.txt
# _8 H5 `0 [4 R - buntu Linux% s( a- z, H; M( h' ~; k
- icrosoft Windows! q5 i8 L q# b4 t, m+ V
- sX El Capitan$ v7 z4 z# z1 [7 n q Q2 |4 o; H: P
- nix
% Q( P3 v. {+ P" C' [' L - reeBSD</font>
复制代码
7 A- P# }' w( Q( ]- A$ v
提取第一到第四个字符:
* g& b/ ?" {# u/ ^6 Y7 h- cut -c-4 content.txt
& x! I+ b, A- E# H4 V5 _; k2 B; J - Ubun% @ d9 `2 J! ]& `! k+ k
- Micr9 ?* o b$ v6 \$ w/ u: U
- OsX% U5 g/ s; P5 h1 }' _4 l2 N
- Unix6 m2 I2 n! v9 @7 N' W& D
- Free
复制代码
0 R0 H- @7 Z9 z0 J0 m8 n& [ A$ j! H9 W# g: E* G! P
' R& o3 z7 }3 _$ w) ~
如何根据字节提取 6 V* b! e3 l8 o) D
8 P0 {) }/ R4 z B
使用-b选项通过指定字节的位置来选择一行的某一部分,使用逗号分隔每个指定位置,或用连字符 - 指定一个范围。 下面这个例子提取 content.txt 文件每一行的第一,二,三个字节: - <font color="black">! u) |2 @0 j( P+ D+ B# {3 Y+ T2 }
- $ cut -b 1,2,3 content.txt - H, O: n# z0 g6 G* [1 R
- Ubu) b- f! I/ h: S& Y
- Mic3 c0 j8 u7 z$ K/ b! Y
- OsX6 J* T! n+ u/ G; Z' W5 [
- Uni) o* \9 U3 i+ e4 _/ g0 Q) A* B7 B" e
- Fre</font>
复制代码- Z* r2 [, D- V/ L$ K& R
我们也可以用如下命令列出一个范围; - <font color="black"> u% x% o* V. }
- $ cut -b 1-3,5-7 content.txt ' X, o% [- a& G' G- x& O! f9 C8 O
- Ubutu ; I* r* q" D$ P( D/ B
- Micoso
6 a% ]& k8 D6 N$ P% ~ b - OsXEl
' d+ Z- @* R1 `! Z) b" K. n3 C - Uni2 ` z8 M2 l, _, L; d7 K
- FreBSD</font>
复制代码/ c/ v% _1 T! ~% t; E8 S% y+ ^) |
% w8 i& s( U8 L8 U. f
一些实用的例子
" J8 ]$ T9 C2 h# x& k2 H7 j9 h6 W: k
cut 是一个实用的命令,常常和其他Linux或Unix命令结合使用 。 例如如果你想提取 ps 命令中的 USER,PID和COMMAND: - <font color="black">2 E) M2 x8 H6 E) |# K; C
- ps -L u n | tr -s " " | cut -d " " -f 2,3,14-
B; o3 e9 o9 c6 O( Z) l0 D: p - USER PID COMMAND
2 @. u3 K: l+ W - 0 676 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyS0 vt2200 y% ]" x3 _" Y7 {7 S: n5 C
- 0 681 /sbin/agetty -o -p -- \u --noclear tty1 linux
Z7 I5 Z1 B' _- a - 0 23174 -bash: R) J4 M! h1 }) b' G
- 0 26737 ps -L u n! u1 z) E8 S+ y/ I3 o
- 0 26738 tr -s
9 }- k/ d& K% {/ G - 0 26739 cut -d -f 2,3,14-</font>
复制代码1 Q8 b& A: F2 S2 r: D3 F3 D
再测试一个例子,提取内存的 total,used和free值,并保存到一个文件中。 - <font color="black">
" n) J( f3 M9 ]3 m - $ free -m | tr -s ' ' | sed '/^Mem/!d' | cut -d" " -f2-4 >> memory.txt( d' d+ P! {, u |8 c# i
- $ cat memory.txt
. |" e$ V! Z& Y3 ^# X8 Y$ @: | - 985 86 234</font>
复制代码2 L. _7 H$ v. L. _4 Q
% w# d) \' s1 h$ J7 `1 T
总结 # b* L7 w0 i, M$ j9 G
- t" q# p& K6 \1 K
cut 命令可以和很多其他Linux或Unix命令通过管道连接。可以通过管道传递一个或多个过滤器进行额外的文本处理。 cut 命令的局限性之一是它不支持指定多个字符作为分隔符。多个空格会被计算为多个字段分隔符,因此必须在 cut 命令前使用 tr 命令才能获得需要的输出。
$ Q* _8 F" t% K+ k/ y! r! F+ @ |