|
cut 命令在Linux和Unix中的作用是从文件中的每一行中截取出一些部分,并输出到标准输出中。我们可以使用 cut 命令从一行字符串中于以字节,字符,字段(分隔符)等单位截取一部分内容出来。 在本文中,我们通过一些例子来了解 cut 命令的使用,这些使用方法在我们的日常工作中也是非常常用的。 ' S0 R; r2 ?, S
Cut 命令和语法
+ Q G ^# S! q: ]6 D2 Z. J% [ }. X. }3 E% X4 x
cut 命令的基本语法如下: - <font color="black">
4 L }6 ~/ Y' c. S6 i1 F3 X' ` - $ cut OPTION... [FILE]...</font>
复制代码
3 u1 t( X" W c8 b! K
我们先来了解一下 cut 的一些选项,cut 命令必须要指定选项才能执行。 -f : 提取指定的字段,cut 命令使用 Tab 作为默认的分隔符。 -d : Tab 是默认的分隔符,使用这一选项可以指定自己的分隔符。 -b : 提取指定的字节,也可以指定一个范围。 -c : 提取指定的字符,可以是以逗号分隔的数字的列表,也可以是以连字符分隔的数字的范围。 –complement : 补充选中的部分,即反选。 –output-delimiter : 修改输出时使用的分隔符。 --only-delimited : 不输出不包含分隔符的列。 我们以如下的名为 context.txt 的文本文件和 /etc/passwd 文件来为例来进行说明。
6 T4 t0 z& C, v; T3 T- $ cat content.txt 3 H$ g* i% c! U, C
- Ubuntu Linux) B9 L2 M2 g( ~
- Microsoft Windows
5 [% S# g/ J7 H - OsX El Capitan
' R* e; Y" _& s2 r( J9 j) @/ t - Unix
, A, B4 b) M* t - FreeBSD
复制代码- t/ ]+ M" b8 ?* J, P2 t$ h9 k0 C
如何指定分隔符 7 t! k2 k0 I, @. a3 v
% Y% \: K9 w R
最常用的选项是 -d 和 -f 的组合,这会根据 -d 指定的分隔符和 -f 列出的字段来提取内容。 例如在这个例子中只打印出 /etc/passwd 文件每一行的第一个字段,用的分隔符是 : - <font color="black"># }# e5 n: y8 I* |1 E* V* c7 u
- $ cut -d':' -f1 /etc/passwd
5 |' u* `) S3 [% b5 S; x/ I - root
4 Y/ ]3 j$ O7 R. b) {8 C - bin4 t# k# k4 I+ o5 w( P* ^2 I S
- daemon
& r' d7 R" O9 x. `" f - adm- e. B( G) k) O
- lp
+ d, o' L' R: s: ]! d - sync/ `. W6 N8 N9 F! F* i" w; \
- shutdown
9 y" U9 p \) n" q7 F$ e - halt
' |* S) e& ?1 }) \3 X" b' C2 ? - mail% R8 I9 ^/ s4 _( B1 ~
- operator
! O+ ]0 `. |; n/ {6 N% G7 I) C - games: w5 C; S |; U/ N+ T3 T
- alvin& W8 T# L2 m- G8 u/ T
- liangxu y7 E1 h0 L K7 g2 H! p7 f, z$ l
- ...</font>
复制代码
9 X! h7 P: j4 n
在下面这个例子中我们用空格作为分隔符打印 content.txt 文件的第一个字段 - <font color="black">8 a2 u( n' _' Z( f& H9 k+ H
- $ cut -d " " -f 1 content.txt ! ^2 B m! e2 ?5 f9 ~5 f- m, V
- Ubuntu
% D; ?# |! p$ u3 C9 Z% i7 e3 N - Microsoft
- A& b( S2 P- g - OsX
" A' J* f0 \4 k, d4 f. \ - Unix
- g M5 o ?. r - FreeBSD</font>
复制代码: z% x8 _% ~* l$ d( r: X3 V4 Q) t& Z
在下面这个例子中我们提取了多个字段。这里,我们使用冒号(:)分隔符从文件 /etc/passwd 中包含字符串 /bin/bash 的行提取第一和第六个字段。 - <font color="black">' s: O7 l5 o; q0 Q7 L* W
- $ grep "/bin/bash" /etc/passwd | cut -d':' -f1,6 `. f& K/ y( i) {
- root:/root
' |* S" \2 ~2 U0 _ - alvin:/home/alvin</font>
复制代码, N4 M2 D# P$ K/ D' U; D
要显示字段的某个范围,可以指定开始和结束的字段,中间用连字符(-)连接,如下所示: - <font color="black">; h0 @+ |; d, e
- $ grep "/bin/bash" /etc/passwd | cut -d':' -f1-4,6,7
' `) f W) ~$ J! ` - root:x:0:0:/root:/bin/bash
/ J2 o7 H# |/ } - alvin:x:1000:1000:/home/alvin:/bin/bash</font>
复制代码
3 Q0 }8 C3 C& }% ]3 @7 o# C
4 g5 b9 X. s" q' d- ]5 ]0 |5 h
如何补全选择的输出
% |9 } U- ?4 q5 U4 u* n3 G+ ^# t8 [
* m1 x6 p" M* a( A
要补全选择输出的字段(即反选),使用 --complement 选项。这一选项输出所有的字段,除了指定的字段。 在下面这个例子中输出 /etc/passwd 文件中包含 /bin/bash 的行中除了第二个字段以外的所有字段: - <font color="black">
9 C: w. e) q% [& _+ A" v - $ grep "/bin/bash" /etc/passwd | cut -d':' --complement -f2
/ _$ M; e5 ], L - root:0:0:root:/root:/bin/bash</font>
复制代码3 L5 }; k3 I( O% F8 @' ~ t
9 Q$ ^6 k, c6 m. F' a9 i# n6 S
如何指定输出的分隔符 7 r! R( P! @4 J5 X+ x- K5 k5 R
+ B p* ?4 e- @ S5 c' t
使用 --output-delimiter 可以指定输出的分隔符。输入的分隔符由 -d 来指定,而输出分隔符和输入分隔符默认是一样的。 我们先以下面的例子来测试不指定输出分隔符时的输出; - <font color="black">
' x4 ?- n% b; S$ O - $ cut -d: -f1,7 /etc/passwd | sort | uniq -u& _$ P) ]( t! {
- _apt:/usr/sbin/nologin
$ H' I1 f$ N& n - backup:/usr/sbin/nologin$ q9 Q3 k5 T% X3 B' G
- bin:/usr/sbin/nologin
6 L) O! L6 Z4 T9 |" t1 Y - daemon:/usr/sbin/nologin5 ^/ r2 a% e1 b0 j, M5 E) ^
- dnsmasq:/usr/sbin/nologin
4 [2 |) N$ J5 v }' w" B# L3 i$ o/ p - games:/usr/sbin/nologin
( U, `! q: ?9 N. R8 }0 l! b2 L - gnats:/usr/sbin/nologin; x: t; M$ f& K" ?
- irc:/usr/sbin/nologin( w9 Q, t3 d1 z1 v0 d
- landscape:/usr/sbin/nologin
+ \: M2 _; B/ ~' a9 F - list:/usr/sbin/nologin
, _8 o" X8 z# F9 w0 e - lp:/usr/sbin/nologin
4 Z9 Y% o- u' [ p - lxd:/bin/false</font>
复制代码
! c% f$ t8 h0 U: R# x2 i
现在我们加上--output-delimiter选项,将输出分隔符指定为空格: - <font color="black">
1 W) i( B" |9 c9 u. ~3 v - $ cut -d: -f1,7 --output-delimiter ' ' /etc/passwd | sort | uniq -u
' G/ a& K8 _/ ]! q' M% H6 w - _apt /usr/sbin/nologin. `) h7 |1 N! |6 Z3 V# P
- backup /usr/sbin/nologin
1 N, d$ R' Q6 {/ @5 ? - bin /usr/sbin/nologin
7 Y# N2 ?$ t: l9 b2 U6 u* X - daemon /usr/sbin/nologin! n8 z2 O) C3 h7 H5 y3 F
- dnsmasq /usr/sbin/nologin
: M5 }# E [8 p* N( ^ - games /usr/sbin/nologin
+ t; m( `3 Z0 {+ s# |6 U+ @ - gnats /usr/sbin/nologin6 o: C) ^1 [- C& Q
- irc /usr/sbin/nologin
8 v+ D& D; m# X: v- e1 f" {4 N - landscape /usr/sbin/nologin. X/ H5 F, H. q6 w# f0 w# F
- list /usr/sbin/nologin8 T6 ?3 Z; h. I0 f2 w& Y9 `6 g
- lp /usr/sbin/nologin
; l$ V" i0 b' ?) j# x) | - lxd /bin/false</font>
复制代码" Z/ \+ { U/ |7 P
我们再测试一个例子,用分隔符让每一行打印一个字段。 我们将 --output-delimiter 指定为 $'\n' 表换行。 输出结果为:
0 Y; o2 Z% u* c; {- $ 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], ?& ~) G" v$ Y4 n
- [/color][/font][/backcolor]
$ M- J* Y& t3 ^8 S0 ]& G2 M - [/p][align=left][backcolor=rgb(255, 255, 255)]
& ?4 y3 ^* j3 F8 z# ^; } - [/backcolor][/align][p=23, null, left][font=Tahoma][color=black]如何以字符的方式提取内容[/color][/font][/p]6 o, ^6 y% X! i: J3 e A
- [align=left][backcolor=rgb(255, 255, 255)]6 _2 t0 M8 W& H2 v
- [/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">$ W$ F0 A5 L8 t! [% n
- $ cut -c 1 content.txt
( H8 i% [$ {+ l/ @6 ^: ?7 g3 r - U3 B! v& ~7 h7 ]. V1 ^' Q4 I
- M0 [3 p6 a& u5 |- m, _, a
- O% i- s4 V: T# B `* |- @
- U
9 V3 R! a9 p& W) i, a& F9 _ - F</font></font>
* T( x5 y+ ]- `. u! ~9 f& P! }
复制代码下面显示了 context.txt 文件每一行的第一至七个字符;
$ W( Q- J' Q Q/ n- T. T; N1 G- $ cut -c 1-7 content.txt c: x# L- C5 { l: |
- Ubuntu( J3 {3 A* Y5 \/ Q: c+ {& ^6 o' }
- Microso( D$ I( q6 {+ X7 F6 Q
- OsX El4 z7 f# X8 [. q5 G+ r$ T+ h
- Unix
9 d; D/ K8 _3 R - FreeBSD
复制代码# H! E! G5 ?4 h! J$ o
我们再测试一下只指定开始或结束的位置。 下面提取第二个到最后一个字符: - <font color="black">
7 F( W9 p' ?: J - $ cut -c2- content.txt
W$ C3 D7 v) w( e - buntu Linux& o) f) c7 F& x# D \ M
- icrosoft Windows
) O2 G8 F ?- _" _6 W - sX El Capitan
% S5 z+ o( H# L - nix2 j' _1 l' i6 e& i0 |1 a% c# k8 \
- reeBSD</font>
复制代码! B/ ~" [# G f$ u
提取第一到第四个字符:
/ [% E2 Q$ w/ Z2 s5 S' K n& ^- cut -c-4 content.txt3 q* J1 `- n& G7 I9 d
- Ubun/ s) F' s" X: X; ]# r
- Micr5 b) [: ~2 Z; _9 W, a, A: }% u, r
- OsX* t; { n! h4 D; b/ {3 ^
- Unix
1 G Y1 d/ H% }; P' D - Free
复制代码
2 g0 q; t% D# a. ^. C6 I% T. P& E' u( s* g. I
( _ z& _5 y% z) A( D) v
如何根据字节提取
3 ]: e2 t- k6 F7 ?* F* k) O! K3 T0 [+ S8 q
使用-b选项通过指定字节的位置来选择一行的某一部分,使用逗号分隔每个指定位置,或用连字符 - 指定一个范围。 下面这个例子提取 content.txt 文件每一行的第一,二,三个字节: - <font color="black">
7 M2 B2 j; `+ R! I/ i - $ cut -b 1,2,3 content.txt $ @% a1 ?& U9 Y. H& U# [
- Ubu: M' f, \+ X" t3 F
- Mic3 i+ t) ?$ f& V6 M4 j
- OsX9 ?. N8 j% k) B. p
- Uni
$ R4 |' B2 U8 M - Fre</font>
复制代码
! d$ `4 x, M& r0 K Q9 `7 c3 {. H
我们也可以用如下命令列出一个范围; - <font color="black">2 n+ f. ]8 g) h: z& I2 b8 W$ {6 B
- $ cut -b 1-3,5-7 content.txt
- k3 {+ r: h: a+ G" v* U$ i$ k - Ubutu / a- o1 W/ c; X; Q
- Micoso
, D5 h3 y2 P3 V* \8 `* W2 e: [$ i - OsXEl
3 ]: E0 x5 P- u9 m' U) S - Uni4 ^- @2 P' K" m# W3 v! a* Z+ D
- FreBSD</font>
复制代码& Y7 @, L5 Y Y, M+ q/ _+ W
. ]# S( w. Y8 N3 w% Y0 C9 K
一些实用的例子
6 N. q! n1 }) f; j* M9 C4 N& n. b1 M- c* l. g+ C, s, Y Y! F
cut 是一个实用的命令,常常和其他Linux或Unix命令结合使用 。 例如如果你想提取 ps 命令中的 USER,PID和COMMAND: - <font color="black">
) Z* t# W1 Q% w4 k6 a# d. u - ps -L u n | tr -s " " | cut -d " " -f 2,3,14-
/ p, R$ k/ P( S) V) y" D - USER PID COMMAND
- G4 r j( I* T- _ - 0 676 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyS0 vt220# [. G4 u9 `6 A, q1 q) n
- 0 681 /sbin/agetty -o -p -- \u --noclear tty1 linux
5 _' U$ k; |6 `2 S' j/ V) S% Q/ V - 0 23174 -bash
: L0 L0 y7 f$ p/ P- C* S0 i; F - 0 26737 ps -L u n
* M4 X, ^& x3 X9 S& c2 }5 r - 0 26738 tr -s
0 {1 B0 q" S- d - 0 26739 cut -d -f 2,3,14-</font>
复制代码5 I- ~% ~; G+ }' E3 N4 ]3 F
再测试一个例子,提取内存的 total,used和free值,并保存到一个文件中。 - <font color="black">
7 y0 `' J% C/ O2 R8 Z - $ free -m | tr -s ' ' | sed '/^Mem/!d' | cut -d" " -f2-4 >> memory.txt% s+ A# z+ M2 F3 x
- $ cat memory.txt
3 r% u% I, `( ?5 | - 985 86 234</font>
复制代码' D5 Q( S" ?. H
M/ S" o" T( j4 F# V
总结 ' ?( G0 h9 i. c6 ]
7 x9 `; X5 G6 g' M* P Q
cut 命令可以和很多其他Linux或Unix命令通过管道连接。可以通过管道传递一个或多个过滤器进行额外的文本处理。 cut 命令的局限性之一是它不支持指定多个字符作为分隔符。多个空格会被计算为多个字段分隔符,因此必须在 cut 命令前使用 tr 命令才能获得需要的输出。
5 `7 x, H) K9 n ], g\n'
2 A. V' V2 z3 V( I& Y8 Rroot/ d4 P* j5 a2 A5 |9 f4 Y
/root
, d" M- E6 Q/ M/bin/bash# f' a$ ^( q, Q! h
operator- A1 f/ @- x( D- T# i( u
/root4 D: t: f2 `6 i+ z
/sbin/nologin[/code]' k& a" x7 z% e+ m; F; l4 S2 D* {2 a
' i. x3 V& `1 a2 }. y
) D( U' D" B+ s
如何以字符的方式提取内容
& x7 P. B$ f% [4 u8 T' h) x5 T+ B
: S# y" n. D5 o# _; }
-c选项可以用来根据字符位置进行提取,注意空格和Tab也以字符来处理。 打印 context.txt 文件每一行的第一个字符,如下: - <font style="background-color:rgb(255, 255, 255)"><font color="black" face="Tahoma">
) H% j/ C) u# r5 N0 u - $ cut -c 1 content.txt
6 i L; g" o$ n9 g' J - U
# V- B# D' c6 x; c" M, U - M' i7 V( I1 r& k
- O' [1 W {: P) R
- U
) p9 C, l4 f. L- Z - F</font></font>4 Y8 R" s% X* ]
复制代码下面显示了 context.txt 文件每一行的第一至七个字符;
4 \! M$ n% L) O/ m& A- p# E6 L- $ cut -c 1-7 content.txt/ R% P* O* x1 f
- Ubuntu' J) \# E. o8 @1 {
- Microso
. }4 J+ a# b3 m6 n - OsX El
+ a( X6 f9 {5 @. S# ^2 k - Unix8 A8 e& t5 B' [( w! y% e- I! t
- FreeBSD
复制代码7 G7 `8 P1 v) T9 J+ F- c7 k1 w" |
我们再测试一下只指定开始或结束的位置。 下面提取第二个到最后一个字符: - <font color="black">) Q$ h- ?( t( E9 F, Q
- $ cut -c2- content.txt4 ]/ b; t# V* K) T6 E4 c
- buntu Linux. d" b% b4 c# r3 `- b) ]* R# J
- icrosoft Windows' W0 U/ `+ _4 ]1 f/ t/ W
- sX El Capitan, U- V( A; L$ @/ j' a
- nix8 D% F1 \7 d! B- a7 f3 u! H) ^' _
- reeBSD</font>
复制代码
) }5 b2 a' d- Y% r8 X
提取第一到第四个字符: - 6 v$ {, Y2 s" ^0 w
- cut -c-4 content.txt
! ~0 j. R, U N$ F/ z - Ubun
! K7 Q' h+ i6 `$ C( R - Micr D, e2 ^7 V0 f% ]1 m& S
- OsX
' Y" w& r9 v* }- C+ p, { - Unix. `4 r k& I" k. O
- Free
复制代码
, K# w" h' y/ r0 }3 H2 I1 @' v$ W/ c# k) ~$ a$ Q+ M
% ^& P5 B) |% x- h
如何根据字节提取
/ T+ g# t$ R( s* b# I; y6 D! ^" s2 I z, \: V% k$ n7 r
使用-b选项通过指定字节的位置来选择一行的某一部分,使用逗号分隔每个指定位置,或用连字符 - 指定一个范围。 下面这个例子提取 content.txt 文件每一行的第一,二,三个字节: - <font color="black">
' Z6 s) L( y5 l# @+ h% k5 b - $ cut -b 1,2,3 content.txt
: ?! V. |; n6 z8 N3 X1 Q/ K - Ubu
7 w, Z# D: o. D) f - Mic
6 x5 @' y" O( f1 w - OsX1 C) ~# q$ r' }; v& j
- Uni4 w* \% E& \2 \. t) z+ Z) d3 l! y# q. z
- Fre</font>
复制代码5 b9 m8 C* d% @: H) A
我们也可以用如下命令列出一个范围; - <font color="black">5 e& K5 C8 \# E- u. B. f) H3 J7 o- `
- $ cut -b 1-3,5-7 content.txt , H0 L( x. p+ R# u
- Ubutu
5 o- K3 l$ k2 P+ i - Micoso8 E4 P) d) g' L, ]
- OsXEl 2 g- Y9 T0 i3 f. V
- Uni) h2 o9 J" Q1 F' T+ u
- FreBSD</font>
复制代码' I9 a/ }, @9 q: L8 p
5 M! v7 @0 K7 r R& `; k2 y; |( P
一些实用的例子 ~" E* k4 f. o
. G1 ^& O( k5 ^) y
cut 是一个实用的命令,常常和其他Linux或Unix命令结合使用 。 例如如果你想提取 ps 命令中的 USER,PID和COMMAND: - <font color="black">! p( i' v# F# [0 v
- ps -L u n | tr -s " " | cut -d " " -f 2,3,14-
7 Y, |, {* m7 o- z4 @ - USER PID COMMAND
+ K1 P( ^9 f/ |1 [ - 0 676 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyS0 vt220
! X' s4 c, q2 V! j' `' j" m7 E - 0 681 /sbin/agetty -o -p -- \u --noclear tty1 linux
8 s X( }6 @* I2 o - 0 23174 -bash9 H9 o$ F- S/ S2 j$ ? l; b) |8 d
- 0 26737 ps -L u n
+ M z: p7 K- f5 U$ `* ~& { - 0 26738 tr -s$ d$ O9 B) A: I
- 0 26739 cut -d -f 2,3,14-</font>
复制代码
( ?/ ^9 r) O- o# I6 G4 @5 W
再测试一个例子,提取内存的 total,used和free值,并保存到一个文件中。 - <font color="black">
8 f# Y- W6 j8 v6 Y - $ free -m | tr -s ' ' | sed '/^Mem/!d' | cut -d" " -f2-4 >> memory.txt" u6 m% `% M4 ?: ^
- $ cat memory.txt
7 y; ?8 @! m7 \! v! P5 n5 E - 985 86 234</font>
复制代码' ]+ L+ I9 A& q
6 i( ^9 b1 U! z' d4 e! Y8 t
总结
: A" w% n* ~& T g7 p/ @$ _9 L
* ^( _3 _- V' C* W4 u
cut 命令可以和很多其他Linux或Unix命令通过管道连接。可以通过管道传递一个或多个过滤器进行额外的文本处理。 cut 命令的局限性之一是它不支持指定多个字符作为分隔符。多个空格会被计算为多个字段分隔符,因此必须在 cut 命令前使用 tr 命令才能获得需要的输出。
( i L: R% @8 d8 D8 v |