cut 命令在Linux和Unix中的作用是从文件中的每一行中截取出一些部分,并输出到标准输出中。我们可以使用 cut 命令从一行字符串中于以字节,字符,字段(分隔符)等单位截取一部分内容出来。 在本文中,我们通过一些例子来了解 cut 命令的使用,这些使用方法在我们的日常工作中也是非常常用的。 . Z8 V# w3 l$ h7 b% U2 B" K' |
Cut 命令和语法
7 f! W5 P6 D/ `+ n- w
, b* c- K" F0 \5 O
cut 命令的基本语法如下: - <font color="black">
2 R$ g4 D% ~! F& y# D# Q - $ cut OPTION... [FILE]...</font>
复制代码) J1 R5 V% T" z
我们先来了解一下 cut 的一些选项,cut 命令必须要指定选项才能执行。 -f : 提取指定的字段,cut 命令使用 Tab 作为默认的分隔符。 -d : Tab 是默认的分隔符,使用这一选项可以指定自己的分隔符。 -b : 提取指定的字节,也可以指定一个范围。 -c : 提取指定的字符,可以是以逗号分隔的数字的列表,也可以是以连字符分隔的数字的范围。 –complement : 补充选中的部分,即反选。 –output-delimiter : 修改输出时使用的分隔符。 --only-delimited : 不输出不包含分隔符的列。 我们以如下的名为 context.txt 的文本文件和 /etc/passwd 文件来为例来进行说明。 - 1 p$ _5 |# ~) j2 [) c$ g% i
- $ cat content.txt
4 q; ]$ \6 p# I, c& q - Ubuntu Linux+ C% ~, l- I& ~& H+ G2 N* s, S1 t
- Microsoft Windows( I I; q0 A% Z/ q# { {
- OsX El Capitan
3 G7 a D7 S4 c( U$ a - Unix
3 j) @; X4 i" q1 E* ? - FreeBSD
复制代码
) |: f4 n) @1 i6 Z1 M/ b
如何指定分隔符
+ E: P/ n) G* \! b8 s/ a% T# b4 s! }4 O$ D
最常用的选项是 -d 和 -f 的组合,这会根据 -d 指定的分隔符和 -f 列出的字段来提取内容。 例如在这个例子中只打印出 /etc/passwd 文件每一行的第一个字段,用的分隔符是 : - <font color="black">
5 {3 q. i1 h# z2 t2 { - $ cut -d':' -f1 /etc/passwd
6 E. o& f" L l - root8 U* N+ l0 L. Y1 t
- bin% `) r9 x0 ]4 }1 @$ h: s
- daemon
& A3 z1 O8 t4 V& |* I - adm
( c! ]0 o) t7 b. G4 Y8 R9 w - lp
: z; R \' F8 b) }$ G! g1 L - sync' i$ M/ W' x! U
- shutdown3 p4 u% Z5 {' ^1 [
- halt
, O+ n6 u9 s/ m2 Z% i - mail
& f; G5 F& T3 G6 K8 q: T, q; L4 O - operator
9 D ]- k* W, M, i - games$ v. B( b7 Q, z3 [
- alvin
4 O1 y# f1 ^, a1 R# S. I( U0 K; ~6 U - liangxu9 v3 [& ^# j0 q6 j7 _& F5 ?; n
- ...</font>
复制代码
; J; R! G* O( }
在下面这个例子中我们用空格作为分隔符打印 content.txt 文件的第一个字段 - <font color="black">
i% x0 `* b, \* z) w - $ cut -d " " -f 1 content.txt ) {$ B# D1 D% C* |- F2 l5 `. i# Q U
- Ubuntu
' @) v" F# I( c5 q/ P& @- S% d* y - Microsoft
$ D, k9 x% Z. e6 J, o - OsX( e+ R$ e0 R1 t, `# u0 s2 }/ m
- Unix
/ N9 z/ K, v! J& X' g - FreeBSD</font>
复制代码
8 |: D; ~: w4 V# [3 x) x
在下面这个例子中我们提取了多个字段。这里,我们使用冒号(:)分隔符从文件 /etc/passwd 中包含字符串 /bin/bash 的行提取第一和第六个字段。 - <font color="black"># e' A( F( P' U2 |. d/ K
- $ grep "/bin/bash" /etc/passwd | cut -d':' -f1,6
: N. S4 F( ?+ M0 `8 S. \+ M1 P0 v6 L2 s# q* l - root:/root
# ]$ B u4 @4 Y1 {/ W - alvin:/home/alvin</font>
复制代码1 f+ E [- q, ?2 K S
要显示字段的某个范围,可以指定开始和结束的字段,中间用连字符(-)连接,如下所示: - <font color="black">
- V5 p$ J$ F9 N: Q - $ grep "/bin/bash" /etc/passwd | cut -d':' -f1-4,6,7& O5 o, C0 L( d; J
- root:x:0:0:/root:/bin/bash
. l0 w) z& }( c5 S4 R4 ?. ]+ s - alvin:x:1000:1000:/home/alvin:/bin/bash</font>
复制代码# _) \/ ?% m+ v9 d
$ P4 g& _1 L9 t( ^$ O S
如何补全选择的输出 8 z. C$ P! c# d& p8 L; L4 M
# |# w. A: J9 }- ~ O1 L* s
要补全选择输出的字段(即反选),使用 --complement 选项。这一选项输出所有的字段,除了指定的字段。 在下面这个例子中输出 /etc/passwd 文件中包含 /bin/bash 的行中除了第二个字段以外的所有字段: - <font color="black">
8 l: h% s0 O! J8 Y8 l; k, Z - $ grep "/bin/bash" /etc/passwd | cut -d':' --complement -f2
( y. i% U) n+ T' a( |3 @# ~) @) w' j - root:0:0:root:/root:/bin/bash</font>
复制代码: @6 X- l& }( F8 F
+ p* ^( W' A; }
如何指定输出的分隔符
+ g. m3 l/ p o( P. k X
& Z0 W1 \) B% p& @" `& W" V
使用 --output-delimiter 可以指定输出的分隔符。输入的分隔符由 -d 来指定,而输出分隔符和输入分隔符默认是一样的。 我们先以下面的例子来测试不指定输出分隔符时的输出; - <font color="black">4 ~; _. e$ {' I. {
- $ cut -d: -f1,7 /etc/passwd | sort | uniq -u& j& C" @9 ~+ T" r- U3 X# _
- _apt:/usr/sbin/nologin) v5 W) `7 T p6 w3 O
- backup:/usr/sbin/nologin9 b% O/ e% i0 V# d- z' K" S: y
- bin:/usr/sbin/nologin9 r [7 [; T7 ]& { N
- daemon:/usr/sbin/nologin
3 y8 l! `+ L" z; b: Q4 v2 p! y - dnsmasq:/usr/sbin/nologin2 e; D0 d2 y/ ]! m3 v0 P. s! |
- games:/usr/sbin/nologin& a2 B8 S2 E& e% }5 ~7 f& U
- gnats:/usr/sbin/nologin0 N8 s, y# R$ @8 v4 [, A* X" d
- irc:/usr/sbin/nologin% z4 R U5 m; q; I% T
- landscape:/usr/sbin/nologin; B" h8 H/ \ q$ @, y
- list:/usr/sbin/nologin4 l9 X8 @% X# [( T5 M
- lp:/usr/sbin/nologin6 X/ y1 s* Z% h. a6 D/ a3 s4 R
- lxd:/bin/false</font>
复制代码$ W* w8 Y' y" r9 m" y
现在我们加上--output-delimiter选项,将输出分隔符指定为空格: - <font color="black">* X+ x0 U0 f6 v
- $ cut -d: -f1,7 --output-delimiter ' ' /etc/passwd | sort | uniq -u
( Y% i0 K" D: ^0 S; J - _apt /usr/sbin/nologin
4 k$ b- q6 J9 ^! t- C4 a& I5 x& Y - backup /usr/sbin/nologin6 H3 r% D* F2 i' Q, _$ ^1 i; O
- bin /usr/sbin/nologin+ P6 |0 Q0 K; w/ \
- daemon /usr/sbin/nologin
7 W. A, T* r5 ~1 S( }6 C - dnsmasq /usr/sbin/nologin
" c) |$ |+ S5 K5 @4 a. D, r U$ ? - games /usr/sbin/nologin
! \7 U) [: [6 z* ]& J - gnats /usr/sbin/nologin
4 `2 e o+ C# b5 F - irc /usr/sbin/nologin
& t6 Q* o8 C ~2 j* G* \ - landscape /usr/sbin/nologin
8 T7 f6 d5 Y, } - list /usr/sbin/nologin
- i2 j+ {+ s9 a" _$ Q# S! V - lp /usr/sbin/nologin! {% p9 u9 o" |) \
- lxd /bin/false</font>
复制代码
2 a8 M/ a: S7 |6 S
我们再测试一个例子,用分隔符让每一行打印一个字段。 我们将 --output-delimiter 指定为 $'\n' 表换行。 输出结果为: - 2 R3 X* w0 v' m
- $ 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]' Z1 W. a: r" V, ]8 d F' t0 p
- [/color][/font][/backcolor]- [2 Y: P: Z, f0 y) B7 O" ^$ b2 b
- [/p][align=left][backcolor=rgb(255, 255, 255)]) s3 k: M$ J* j( p0 Q- J2 k
- [/backcolor][/align][p=23, null, left][font=Tahoma][color=black]如何以字符的方式提取内容[/color][/font][/p]! h6 d/ W7 ], v; d) k8 ?
- [align=left][backcolor=rgb(255, 255, 255)]/ ~/ I* D9 T' |7 u* J: u
- [/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">
% r* D+ d$ r6 M+ x }- ?- { - $ cut -c 1 content.txt
5 r K$ }" t3 @8 s% }. J2 y - U
7 v- X" h5 @: L& Y. w! L2 s - M8 S2 R3 w3 ]4 X5 n/ d* k' W* ^! X4 }
- O
( P4 h. ]$ V2 }0 D9 o; p9 U - U
+ ]: F6 b) H: Z% [. U3 T - F</font></font>- W4 h6 S/ z8 H: C7 o" n
复制代码下面显示了 context.txt 文件每一行的第一至七个字符;
1 Y+ [2 `$ `4 r6 f% z- $ cut -c 1-7 content.txt a2 j) n% ^3 Y- |/ k
- Ubuntu
' `7 x6 Y6 b5 T' d' U7 C - Microso
6 s3 L/ E q: V. S - OsX El
1 q# Q3 R) e; z" U) D - Unix
% f8 k, C/ c6 K( M, z - FreeBSD
复制代码; z* \# c6 I) G) T' M- t
我们再测试一下只指定开始或结束的位置。 下面提取第二个到最后一个字符: - <font color="black">
6 R' u- { O% S7 `4 X, N2 P - $ cut -c2- content.txt4 R& h1 ~. {: c. [- ]" ? [
- buntu Linux! J$ v% A( t9 h: R, I( }7 y
- icrosoft Windows& h5 K, q- F4 ^, E( o
- sX El Capitan
9 V) q" R: Q5 G. v! K; Z$ f - nix
, [! \: `- w. g9 B' [) Z - reeBSD</font>
复制代码6 m8 Z9 j' R* g! j( ?7 a" [
提取第一到第四个字符:
% C. q; g/ W2 \+ F/ q b+ y- cut -c-4 content.txt, `4 @8 b3 l2 C# t0 }( C
- Ubun9 b- F7 ~2 ]. u$ H
- Micr- g; G1 j: ^, t
- OsX
6 N2 q, G' q. P$ \& g4 ]: H3 N/ n - Unix
2 s( j# R5 \, v* t. O0 B" \ - Free
复制代码* K) b# z, P# E& [8 d6 ]
& @1 E0 F2 T! _# z$ H6 E 2 e8 a' D% @7 w" h. C% T/ n, ]1 ^4 {
如何根据字节提取 $ K0 I1 ^2 P7 Z; w7 n6 ^" u+ [
, u; U/ V8 N [2 Q! M
使用-b选项通过指定字节的位置来选择一行的某一部分,使用逗号分隔每个指定位置,或用连字符 - 指定一个范围。 下面这个例子提取 content.txt 文件每一行的第一,二,三个字节: - <font color="black">4 |# H1 B5 P6 N P
- $ cut -b 1,2,3 content.txt ) i/ _. J+ N: i: n" d" g; x
- Ubu
0 s! ]( Z4 t ]8 R4 o! [% X/ f; p4 M - Mic
6 W& r, N# B: t+ x( O! ]/ s5 s( V - OsX
% \: R* K9 \8 z - Uni& ?; P2 q# i) h4 A+ S
- Fre</font>
复制代码
" W/ l8 ~ e n/ A
我们也可以用如下命令列出一个范围; - <font color="black">3 M$ y8 T) E" D! I& Z' D9 [. _
- $ cut -b 1-3,5-7 content.txt
: }1 e! o" D* i- u, w - Ubutu : D. [; V0 B9 G
- Micoso
& R" B9 {' h7 M! }' L - OsXEl 9 ?# K" N0 s3 S, i4 S ~. N7 e
- Uni; @7 O- ?8 P0 J3 V0 M+ \$ F
- FreBSD</font>
复制代码! f9 f$ k: h, d; O9 b: {6 f; S1 q
. c1 X/ y7 z+ ]5 u; e* |
一些实用的例子
8 B+ M. q. Y! B) I, @$ j
O% h2 V/ M, e
cut 是一个实用的命令,常常和其他Linux或Unix命令结合使用 。 例如如果你想提取 ps 命令中的 USER,PID和COMMAND: - <font color="black">
' c( Z) b9 E. V: [2 t' P - ps -L u n | tr -s " " | cut -d " " -f 2,3,14-
3 U1 y; b2 m* i7 [4 t - USER PID COMMAND
7 M' y3 |' a' v7 S: o) @; b - 0 676 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyS0 vt220
/ [! U. P( C6 v- d& i, M P - 0 681 /sbin/agetty -o -p -- \u --noclear tty1 linux
5 b/ s6 K3 F' F0 { - 0 23174 -bash
' [% E I' y b$ i e - 0 26737 ps -L u n
* ^) P: y" J& a - 0 26738 tr -s
2 _- H0 I4 ?: n - 0 26739 cut -d -f 2,3,14-</font>
复制代码
" c# @& J$ C/ B% a4 |. Q S; n
再测试一个例子,提取内存的 total,used和free值,并保存到一个文件中。 - <font color="black">
! G2 l. u5 P! H8 p - $ free -m | tr -s ' ' | sed '/^Mem/!d' | cut -d" " -f2-4 >> memory.txt
: ~, B2 K- C9 C% [" C1 g - $ cat memory.txt) t$ f: _- J4 p: r% G
- 985 86 234</font>
复制代码
1 v, X8 \/ t# f* F, Y$ O& R
$ i; G# F3 ^* `0 o
总结 / X/ ~$ j4 j2 X8 \" q2 ^
1 j: \! m4 O+ s7 ~; U9 s. _
cut 命令可以和很多其他Linux或Unix命令通过管道连接。可以通过管道传递一个或多个过滤器进行额外的文本处理。 cut 命令的局限性之一是它不支持指定多个字符作为分隔符。多个空格会被计算为多个字段分隔符,因此必须在 cut 命令前使用 tr 命令才能获得需要的输出。 : t! d) h& ^9 D1 R! i* T
\n') }9 Y, r: _: I( f7 g+ V
root7 {( }. T1 B* Q+ |% J2 C
/root0 b$ w2 X7 ` E& I: }6 N6 h
/bin/bash" |0 Q2 L, K' m$ E5 L
operator0 ?8 Z) q+ |: `, [5 D- i
/root9 a* O P% i: W, [& L
/sbin/nologin[/code]% g0 h) m# K6 u2 k. T! ~. {
7 J* y1 X' A3 }' X2 d : Q7 H, @8 J+ r2 ]# K# ~+ o: j
如何以字符的方式提取内容 : Y1 W2 _( r# T' s$ Z: q
$ B+ Y: y+ l0 w
-c选项可以用来根据字符位置进行提取,注意空格和Tab也以字符来处理。 打印 context.txt 文件每一行的第一个字符,如下: - <font style="background-color:rgb(255, 255, 255)"><font color="black" face="Tahoma">7 z' x0 @4 L9 ^! S. C
- $ cut -c 1 content.txt2 P' |7 b# s( ?: b* l
- U
1 ]: ~* }, a6 E" b# x% s7 I( K3 w+ ?/ c - M
( v4 z5 O% u$ a+ L" V' w C - O( z' |5 ^& [7 j2 R! Q6 g1 }; i3 g
- U1 W! r6 P, u/ ^
- F</font></font>
8 o4 K) H2 S6 P2 c" E) i( M
复制代码下面显示了 context.txt 文件每一行的第一至七个字符;
4 D M- X& E2 E7 Z- R- $ cut -c 1-7 content.txt
w6 r" ~- z" k: k& m9 R2 d- g - Ubuntu; Q) l3 y/ e) w T: ^% g" s
- Microso$ r% n; |: \6 i+ C
- OsX El
* r4 a6 }. j: R - Unix
, n, P: W+ V7 E0 ]9 I - FreeBSD
复制代码/ S' R9 B' |: b0 g8 Z* [ K1 |
我们再测试一下只指定开始或结束的位置。 下面提取第二个到最后一个字符: - <font color="black">
0 c# ~5 g/ [% M/ Y2 n" b - $ cut -c2- content.txt
; i: U- i* z$ V7 U) z' B0 j - buntu Linux
% Z' a: D5 E7 D: h& S# Z' m6 g; H - icrosoft Windows x# E; k2 q" j8 ^+ r$ o
- sX El Capitan
0 [$ {/ |# z! s' r! N - nix
- }. R0 K) `* |9 |: ]0 T1 x - reeBSD</font>
复制代码
" }# H4 ^! s8 W
提取第一到第四个字符:
( \' a. i6 N1 Y; x! Q- cut -c-4 content.txt
2 A7 U* q) m# y* ], J - Ubun
; }) G4 _# q3 E5 F, q/ r3 S - Micr
' w+ ^( U% `& c - OsX) }" ~( A8 v- E! s( b! `# K! b0 [
- Unix
. m* k/ `. g, ]' _) e, K/ y) }% R - Free
复制代码 ?# w# N9 [7 H) `
x6 L. ~5 ~8 `1 o. i, W& u7 y5 {
H; v0 [& k! k( a) |% c
如何根据字节提取 * |( v0 H& O% p. r
) `* z! p$ R5 e. u
使用-b选项通过指定字节的位置来选择一行的某一部分,使用逗号分隔每个指定位置,或用连字符 - 指定一个范围。 下面这个例子提取 content.txt 文件每一行的第一,二,三个字节: - <font color="black">. l& t o: H+ E$ \+ d7 k) a
- $ cut -b 1,2,3 content.txt
( R8 [0 _5 L( i( M5 m7 t o f% o - Ubu6 U9 a+ M! M8 E, P' g
- Mic3 X. g# E7 w7 Y: d0 |. d, Z7 d
- OsX9 Y! l: g+ f4 @6 O9 w( Q+ i: S
- Uni
$ r9 x5 m( g6 R - Fre</font>
复制代码5 u Y1 }8 u# F: k J E) Q K
我们也可以用如下命令列出一个范围; - <font color="black">
; w) P7 w; f. _" k4 G - $ cut -b 1-3,5-7 content.txt 6 g9 W8 i+ B& H o) u: k, ^
- Ubutu % f% E8 U) w+ j- a
- Micoso/ v6 N! G# K7 a% P% g
- OsXEl 8 Q K, _' e$ J5 w5 \1 _- w
- Uni! `2 _' f5 y; n: \
- FreBSD</font>
复制代码& o' i# |8 `3 B' R" N
8 {/ Y3 o1 c% d! G- h: m/ `# y
一些实用的例子
; C+ U! k, N5 Y* ?0 n8 e
6 o& \) H9 K) C
cut 是一个实用的命令,常常和其他Linux或Unix命令结合使用 。 例如如果你想提取 ps 命令中的 USER,PID和COMMAND: - <font color="black">
6 Z, e* ?: @6 t+ I6 q - ps -L u n | tr -s " " | cut -d " " -f 2,3,14-
- Q1 X; W2 _1 b2 z/ I" W - USER PID COMMAND
k; }7 |+ `: T- L d) X - 0 676 /sbin/agetty -o -p -- \u --keep-baud 115200,38400,9600 ttyS0 vt220
' Q" h( N* l0 z, `1 \4 s6 u - 0 681 /sbin/agetty -o -p -- \u --noclear tty1 linux
/ _ W, ~( x( d& h* s - 0 23174 -bash
: `9 r2 ]! A8 u0 X0 r; a - 0 26737 ps -L u n3 H; t) y& {1 M- P& N
- 0 26738 tr -s# z9 h2 ?( ~8 b
- 0 26739 cut -d -f 2,3,14-</font>
复制代码7 u4 t; e# b9 W* d+ z4 Z. w
再测试一个例子,提取内存的 total,used和free值,并保存到一个文件中。 - <font color="black">
4 o+ c8 g' X- F - $ free -m | tr -s ' ' | sed '/^Mem/!d' | cut -d" " -f2-4 >> memory.txt
2 ]/ N! l/ ]' G$ I+ R: I; p - $ cat memory.txt
3 `" S) L- a7 M& f7 W E" j+ v - 985 86 234</font>
复制代码* w0 c2 A6 Z$ M7 O9 M q- ]8 P
* N3 v3 o) o4 @2 `) J U, U
总结
* M& c- ^# A9 E; U/ E
5 J1 l9 A- J( h7 p
cut 命令可以和很多其他Linux或Unix命令通过管道连接。可以通过管道传递一个或多个过滤器进行额外的文本处理。 cut 命令的局限性之一是它不支持指定多个字符作为分隔符。多个空格会被计算为多个字段分隔符,因此必须在 cut 命令前使用 tr 命令才能获得需要的输出。
9 n, S; D. h' n1 G |