grep、sed和awk都是文本處理工具,雖然都是文本處理工具單卻都有各自的優缺點,一種文本處理命令是不能被另外一個徹底替換的,不然也不會出現三個文本處理命令了。只不過,相比較而言,sed和awk功能更強大而已,且已獨立成一種語言來介紹。mysql
awk:報告生成器,格式化之後顯示。若是對處理的數據須要生成報告之類的信息,或者你處理的數據是按列進行處理的,最好使用awk。linux
\?:匹配其前面的字符1次或0次nginx
\{m,n\}:匹配其前面的字符至少m次,至多n次git
\{1,\}:至少一次
分組:web
\(\)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
vim test1
#編輯該文件添加以下內容:
He love his lover.
She like her liker.
He love his liker.
She like her lover.
He like her.
She love he.
[root@www ~]
# grep '\(l..e\).*\1' test1 #匹配前邊第一個左括號的以及與之對應的右括號的內容
He love his lover.
She like her liker.
[root@www ~]
# grep 'l..e' test1 #匹配指定的字符,中間可爲任意兩個字符
He love his lover.
She like her liker.
He love his liker.
She like her lover.
He like her.
She love he.
|
grep練習:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
一、顯示
/proc/meminfo
文件中以不區分大小的s開頭的行;
grep
-i
'^s'
/proc/meminfo
或者
grep
'^[sS]'
/proc/meminfo
#[]表示匹配指定範圍內的單個字符,所以也可實現不區分大小寫
二、顯示
/etc/passwd
中以nologin結尾的行;
grep
'nologin$'
/etc/passwd
擴展一:取出默認shell爲
/sbin/nologin
的用戶列表
grep
'/sbin/nologin'
/etc/passwd
|
cut
-d: -f1 或者
grep
'/sbin/nologin'
/etc/passwd
|
awk
-F:
'{print $1}'
或者直接使用
awk
awk
-F:
'$7 ~ /nologin/{print $1}'
/etc/passwd
擴展二:取出默認shell爲
bash
,且其用戶ID號最小的用戶的用戶名
grep
'bash$'
/etc/passwd
|
sort
-n -t: -k3 |
head
-1 |
cut
-d: -f1 或者
awk
-F:
'$7 ~ /bash/{print $3,$1}'
/etc/passwd
|
sort
-n |
head
-1 |
awk
'{print $2}'
三、顯示
/etc/inittab
中以
#開頭,且後面跟一個或多個空白字符,然後又跟了任意非空白字符的行;
grep
'^#[[:space:]]\{1,\}[^[:space:]]'
/etc/inittab
四、顯示
/etc/inittab
中包含了:一個數字:(即兩個冒號中間一個數字)的行;
grep
':[0-9]:'
/etc/inittab
五、顯示
/boot/grub/grub
.conf文件中以一個或多個空白字符開頭的行;
grep
'^[[:space:]]\{1,\}'
/boot/grub/grub
.conf
六、顯示
/etc/inittab
文件中以一個數字開頭並以一個與開頭數字相同的數字結尾的行;
grep
'\(^[0-9]\).*\1$'
/etc/inittab
#在RHEL5.8之前的版本中可查看到效果
七、找出某文件中的,1位數,或2位數;
grep
'\<[[:digit:]][[:digit:]]\?\>'
/etc/inittab
或者
grep
'\<[0-9]\{1,2\}\>'
/etc/inittab
八、查找當前系統上名字爲student(必須出如今行首)的用戶的賬號的相關信息, 文件爲
/etc/passwd
grep
'^student:'
/etc/passwd
擴展:若存在該用戶,找出該用戶的ID號:
grep
'^student:'
/etc/passwd
|
cut
-d: -f3 或者
# id -u student
|
1
2
3
|
ifconfig
eth0|
grep
-oE
'([0-9]{1,3}\.?){4}'
|
head
-n 1
ifconfig
eth0|
awk
-F:
'/inet addr/{split($2,a," ");print a[1];exit}'
#這裏使用了awk的內置函數,若是不懂可在看完awk的介紹後再來作此題
ifconfig
|
grep
"inet addr"
|
grep
-
v
"127.0.0.1"
|
awk
-F:
'{print $2}'
|
awk
'{print $1}'
|
sed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
cp
/etc/inittab
./
#複製該文件到當前目錄下,這裏當前處於root家目錄下。
vim inittab
#編輯該文件,修改此文件,內容以下所示,其內容也可參看下邊的圖片
# inittab is only used by upstart for the default runlevel.
#
#此處是一空行,沒有任何字符,就光空行添加代碼時會被刪掉,因此這裏加上備註,說明是一空交行,下面相同
# Individual runlevels are started by /etc/init/rc.conf
#
#此處是一空行,沒有任何字符。該文件內容也看參見下邊的圖片
# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id
:3:initdefault:
|
用複製並修過的inittab文件做爲測試文件,舉幾個例子:面試
1
|
[root@www ~]
# sed '1,3d' inittab:表示刪除文件的第一到第三行
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
[root@www ~]
# sed '3,$d' inittab #表示刪除模式空間中的第三到最後一行
# inittab is only used by upstart for the default runlevel.
#
[root@www ~]
# sed '/run/d' inittab #表示刪除被run匹配到的行
#
#
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id
:3:initdefault:
[root@www ~]
# sed '/^#/d' inittab #表示刪除文件中以#開頭的行
id
:3:initdefault:
[root@www ~]
# sed -n '/^\//p' inittab #顯示以/開頭的行,由於沒有這樣的行,故不顯示任何信息
[root@www ~]
# sed '/^#/p' inittab #顯示以#開頭的行,能夠看到被匹配到的行,均顯示了兩遍,這是由於sed處理時會把處理的信息輸出
# inittab is only used by upstart for the default runlevel.
# inittab is only used by upstart for the default runlevel.
#
#
# Individual runlevels are started by /etc/init/rc.conf
# Individual runlevels are started by /etc/init/rc.conf
#
#
# Default runlevel. The runlevels used are:
# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this)
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 3 - Full multiuser mode
# 4 - unused
# 4 - unused
# 5 - X11
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
# 6 - reboot (Do NOT set initdefault to this)
#
#
id
:3:initdefault:
[root@www ~]
# sed -n '/^#/p' inittab #顯示以#開頭的行,使用-n選項表示僅顯示匹配到的行
# inittab is only used by upstart for the default runlevel.
#
# Individual runlevels are started by /etc/init/rc.conf
#
# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
vim
test
#編輯該文件添加以下內容:
Welcome to my linux!
This is my world.
How are you?
[root@www ~]
# sed '2r ./test' inittab #表示將test文件中的內容添加到inittab文件中,且從第二行日後開始添加
# inittab is only used by upstart for the default runlevel.
#
Welcome to my linux!
#新添加的三行內容
This is my world.
How are you?
# Individual runlevels are started by /etc/init/rc.conf
#
# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id
:3:initdefault:
[root@www ~]
# sed '1,2r ./test' inittab #表示將test文件中的內容添加到inittab文件中,且分別 添加在第一和第二行後邊
# inittab is only used by upstart for the default runlevel.
Welcome to my linux!
#新添加的三行內容
This is my world.
How are you?
#
Welcome to my linux!
#新添加的三行內容
This is my world.
How are you?
# Individual runlevels are started by /etc/init/rc.conf
#
# Default runlevel. The runlevels used are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id
:3:initdefault:
[root@www ~]
# sed 's/linux/LINUX/g' test #查找該文件中的字符串,而後替換爲指定的字符串
Welcome to my LINUX!
#能夠看到以替換爲大寫的linux
This is my world.
How are you?
[root@www ~]
# sed 's/y.u/&r/g' test #查找指定的字符串,並將其替換爲在其後加上r,分隔符采用/
Welcome to my linux!
This is my world.
How are your?
[root@www ~]
# sed 's@y.u@&r@g' test #意義同上,分隔符采用@
Welcome to my linux!
This is my world.
How are your?
[root@www ~]
# sed 's#y.u#&r#g' test #意義同上,分隔符采用#
Welcome to my linux!
This is my world.
How are your?
|
sed練習;正則表達式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
一、刪除
/etc/grub
.conf文件中行首的空白符;
sed
-r
's/^[[:space:]]+//'
/etc/grub
.conf
二、替換
/etc/inittab
文件中「
id
:3:initdefault:」一行中的數字爲5;
sed
's/\(id:\)[0-9]\(:initdefault:\)/\15\2/g'
/etc/inittab
三、刪除
/etc/inittab
文件中的空白行;
sed
'/^$/d'
/etc/inittab
四、刪除
/etc/inittab
文件中開頭的
#號;
sed
's/^#//g'
/etc/inittab
五、刪除某文件中開頭的
#號及其後面的空白字符,但要求#號後面必須有空白符;
sed
's/^#[[:space:]]\{1,\}//g'
/etc/inittab
或者
sed
-r
's/^#[[:space:]]+//g'
/etc/inittab
六、刪除某文件中以空白字符後面跟
#類的行中的開頭的空白字符及#
sed
-r
's/^[[:space:]]+#//g'
/etc/inittab
七、取出一個文件路徑的目錄名稱;
echo
"/etc/rc.d/abc/edu/"
|
sed
-r
's@^(/.*/)[^/]+/?@\1@g'
#因sed支持擴展正則表達式,在擴展正則表達式中,+表示匹配其前面的字符至少1次
八、取出一個文件路徑的最後一個文件名;
echo
"/etc/rc.d/abc/edu/"
|
sed
-r
's@^/.*/([^/]+)/?@\1@g'
|
awk是一種優良的文本處理工具,Linux及Unix環境中現有的功能最強大的數據處理引擎之一。這種編程及數據操做語言(其名稱得自於它的創始人Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首個字母)的最大功能取決於一我的所擁有的知識。AWK提供了極其強大的功能:能夠進行正則表達式的匹配,樣式裝入、流控制、數學運算符、進程控制語句甚至於內置的變量和函數。它具有了一個完整的語言所應具備的幾乎全部精美特性。實際上AWK的確擁有本身的語言:AWK程序設計語言,三位建立者已將它正式定義爲「樣式掃描和處理語言」。它容許您建立簡短的程序,這些程序讀取輸入文件、爲數據排序、處理數據、對輸入執行計算以及生成報表,還有無數其餘的功能。最簡單地說,AWK是一種用於處理文本的編程語言工具。咱們如今使用最多的是gawk,gawk是AWK的GNU版本。
sql
1
2
|
awk
'BEGIN { print "line one\nline two\nline three" }'
awk
-F:
'{ print $1, $7 }'
/etc/passwd
#等價於:awk -v FS=: '{print $1,$7}' /etc/passwd
|
2、awk變量shell
2.1 awk內置變量之記錄變量:一塊兒來看一個示例:express
1
2
3
4
5
|
vim
test
.txt
#編輯該文件,添加以下兩行信息做爲示例使用
welcome to redhat linux.
how are you?
[root@www ~]
# awk 'BEGIN{OFS="#"} {print $1,$2}' test.txt #指定輸出時的分隔符
[root@www ~]
# awk 'BEGIN{OFS="#"} {print $1,"hello",$2}' test.txt #指定輸出時的分隔符,並添加顯示的內容
|
1
2
3
4
5
6
7
8
9
|
[root@www ~]
# awk -v FS=: -v OFS=# '{print $1,$7}' /etc/passwd #以:爲字段分隔符,以#號爲輸出分隔符,顯示該文件的第一及第七字段的值,這裏僅貼出部分顯示內容
root
#/bin/bash
bin
#/sbin/nologin
daemon
#/sbin/nologin
adm
#/sbin/nologin
lp
#/sbin/nologin
sync
#/bin/sync
shutdown
#/sbin/shutdown
halt
#/sbin/halt
|
1
2
|
awk
'BEGIN{print ENVIRON["PATH"]}'
awk
'{print $NF}'
test
.txt
|
1
2
|
[root@www ~]
# awk 'BEGIN{var="variable testing";print var}' #給變量賦值,並輸出變量的值,下邊是顯示效果
variable testing
|
1
2
|
[root@www ~]
# awk -v var="variable testing" 'BEGIN{print var}' #與上述的例子同樣,顯示效果以下
variable testing
|
1
|
awk
-F:
'{printf "%-15s%i\n",$1,$3}'
/etc/passwd
#使用printf顯示該文件中的第一列和第三列,要求第一列左對齊且佔用15個字符寬度,第二列顯示十進制整數,顯示效果以下所示:
|
4、輸出重定向
使用格式:
1
|
awk
-F:
'{printf "%-15s %i\n",$1,$3 > "/dev/stderr" }'
/etc/passwd
#顯示效果與上述例子同樣,只不過這裏是重定向到錯誤輸出,而後顯示
|
1
2
|
[root@www ~]
# awk 'BEGIN{print "A" "B"}' #鏈接A和B兩個字符,使其成爲一個字符串,顯示效果以下所示:
AB
|
1
2
3
|
[root@www ~]
# awk -F: '$1 ~ /^root/{print $1,$3,$4,$NF}' /etc/passwd #顯示該文件中以root開頭的行的第一列、第三列、第四列和最後一列,顯示效果以下所示:
root 0 0
/bin/bash
[root@www ~]
# awk -F: '$3>=400{printf "%-15s%-10i%s\n",$1,$3,$NF}' /etc/passwd #顯示UID大於400的行的第一列、第三列和最後一列
|
1
2
3
4
5
|
[root@www ~]
# awk -F: '/bash/{print $0}' /etc/passwd #在/etc/passwd中查找有bash的行,並顯示
root:x:0:0:root:
/root
:
/bin/bash
nginx:x:496:493::
/home/nginx
:
/bin/bash
mysql:x:495:492::
/home/mysql
:
/bin/bash
wpuser:x:494:491::
/home/wpuser
:
/bin/bash
|
1
2
3
|
awk
-F:
'$3>=500{printf "%-15s%s\n",$1,$3}'
/etc/passwd
awk
-F:
'$1 ~ /root/{print $1,$3}'
/etc/passwd
等價於:
awk
-F:
'$1=="root"{print $1,$3}'
/etc/passwd
|
1
2
3
4
5
6
7
8
9
|
[root@www ~]
# awk -F: 'BEGIN{print "Username UID"}$3>=400{printf "%-15s%s\n",$1,$3}' /etc/passwd #上式表示對於該文件,在開始比較前先輸出username和UID做爲題頭,而後,輸出UID大於400的行的第一列和第三列
Username UID
rtkit 499
pulse 498
saslauth 497
nfsnobody 65534
nginx 496
mysql 495
wpuser 494
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
有三中方式都可以實現,命令及顯示效果以下:
[root@www ~]
# awk -v FS=: '{print $1}' /etc/passwd #使用-v選項和FS指定分隔符,而後顯示
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
uucp
[root@www ~]
# awk -F: '{print $1}' /etc/passwd #直接使用-F選項指定分隔符,而後顯示
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
uucp
[root@www ~]
# awk 'BEGIN{FS=":"}{print $1}' /etc/passwd #使用BEGIN,在運行前指定分隔符,而後顯示
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
uucp
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
[root@www ~]
# awk -F: '{if ($1=="root") print $1, "Admin"; else print $1, "Common User"}' /etc/passwd #判斷若是第一個字段是root,則顯示是admin,不然顯示是common user,顯示結果以下所示:
root Admin
bin Common User
daemon Common User
adm Common User
lp Common User
sync
Common User
shutdown
Common User
halt Common User
[root@www ~]
# awk -F: '{if ($1=="root") printf "%-15s%s\n", $1,"Admin"; else printf "%-15s%s\n", $1, "Common User"}' /etc/passwd #顯示效果同上,只不過這裏使用printf,顯示定義顯示的格式
root Admin
bin Common User
daemon Common User
adm Common User
lp Common User
sync
Common User
shutdown
Common User
halt Common User
mail Common User
uucp Common User
[root@www ~]
# awk -F: -v sum=0 '{if ($3>=400) sum++}{if ($3>=400) printf "%-15s%i\n",$1,$3}END{print "Sum = "sum;}' /etc/passwd #定義變量sum=0,而後判斷若是UID大於400,讓sum自加,而且若是UID大於等於400的顯示其用戶名和UID,結束前輸出sum的值
rtkit 499
pulse 498
saslauth 497
nfsnobody 65534
nginx 496
mysql 495
wpuser 494
Sum = 7
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
[root@www ~]
# awk -F: -v i=1 '{while (i<=7) {print $i;i++}}' /etc/passwd #使用-v選項顯示定義變量i=1,當i小於等於7時循環結束,而後,輸出第一個字段到第七個字段,當i爲7時,正好輸出的是第一行的7個字段的值
root
x
0
0
root
/root
/bin/bash
[root@www ~]
# awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd #定義變量i,先判斷,當i小於等於3時,輸出第一到第三個字段的值,所處理的數據時該文件中的每一行數據,而不只僅是第一行。這裏須要注意與上述命令的 區別
root
x
0
bin
x
1
daemon
x
2
adm
x
3
lp
x
4
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[root@www ~]
# awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd #意義同上,顯示效果雖與上述相同,但與while不一樣的是,do-while是先執行一趟,而後再判斷是否知足條件,也就是說無論條件是否知足,都會先 執行一趟;而while中若是條件不知足,則一趟也不會執行
root
x
0
bin
x
1
daemon
x
2
adm
x
3
lp
x
4
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
[root@www ~]
# awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd #使用for循環,輸出各行的前三個字段
root
x
0
bin
x
1
daemon
x
2
adm
x
3
lp
x
4
|
1
2
3
4
5
6
|
[root@www ~]
# awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd #匹配最後一個字段不空的行,把最後一段當作數組下標,輸出各下標的值,及各下標對應的個數,各下標的個數保存在數組中
/bin/sync
:1
/bin/bash
:4
/sbin/nologin
:29
/sbin/halt
:1
/sbin/shutdown
:1
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
[root@www ~]
# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd #UID號對2取餘,若是爲0,直接處理下一行,不然,輸出用戶名和UID號,顯示效果以下所示:
bin 1
adm 3
sync
5
halt 7
operator 11
gopher 13
nobody 99
dbus 81
usbmuxd 113
vcsa 69
rtkit 499
saslauth 497
postfix 89
abrt 173
rpcuser 29
mysql 495
|
1
2
|
netstat
-ant |
awk
'/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
每出現一被/^tcp/模式匹配到的行,數組S[$NF]就加1,NF爲當前匹配到的行的最後一個字段,此處用其值作爲數組S的元素索引
|
1
2
3
4
5
6
7
8
9
10
11
|
[root@www ~]
# awk '{IP[$1]++}END{for (A in IP) printf "%-20s%s\n",A,IP[A]}' /var/log/nginx/access.log #用法與上一個例子相同,用於統計某日誌文件中IP地的訪問量
172.16.32.30 3
172.16.32.50 31596
172.16.32.52 408
192.168.0.239 1886
172.16.32.0 1010
[root@www ~]
# awk 'BEGIN{A["m"]="hello";A["n"]="world";print A["m"],A["n"]}' #開始前對數組賦值,而後輸出數組的值
hello world
[root@www ~]
# awk 'BEGIN{A["m"]="hello";A["n"]="world";for (B in A) print A[B]}' #在開始前對數組賦值,而後使用for循環,把B當作下標,依次輸出數組中的值
hello
world
|
1
|
netstat
-ant |
awk
'/:22\>/{split($5,clients,":");IP[clients[1]]++}END{for(i in IP){print IP[i],i}}'
|
sort
-rn |
head
-50
#顯示效果以下所示:
|
1
2
3
4
5
6
7
8
9
10
11
12
|
vim cfkj.sh
#編輯該文件,輸入以下內容:
#!/bin/awk -f
BEGIN{
for
(i=1;i<=9;i++)
{
for
(m=1;m<=i;m++)
{
printf
m
"*"
i
"="
m*i
" "
}
print
}
}
|
二、打印圖案
1
|
awk
'BEGIN {for(i=1;i<=4;i++) {for(j=1;j<=10-i;j++) {printf " ";}for(j=1;j<=(2*i-1);j++) {printf "*";}printf "\n";}}'
|
1
2
|
echo
15|
awk
'{x=8;
for
(i=1;i<$0;i++){
for
(j=1;j<=3*($0-i)-(x>0?x:0);j++)
printf
" "
;
for
(k=i;k>=1;k--)
printf
"%d "
,k;
for
(l=2;l<=i;l++)
printf
"%d "
,l;
printf
"\n"
;x--};\
for
(i=1;i<=$0;i++){
for
(j=1;j<=(i<=$0-10+1?3*(i-1):3*(i-1)+2-(i-$0%10-10*int(($0-10)
/10
)));j++)
printf
" "
;
for
(k=$0-i+1;k>=1;k--)
printf
"%d "
,k;
for
(l=2;l<=$0-i+1;l++)
printf
"%d "
,l;
printf
"\n"
}}'
|