Linux GNU AWK使用
本章内容:
awk介绍
awk基本用法
awk变量
awk格式化
awk操作符
awk条件判断
awk循环
awk数组
awk函数
调用系统命令
文本处理三工具: grep、sed、awk
grep:文本过滤工具;
sed:行编辑器;
awk:报告生成器,格式化文本输出;
awk:Aho Weinberger Kernighan,报告生成器,格式化文本输出。
awk:有多重版本:New awk (nawk) GNU awk (gawk)。
gawk – 模式扫描和处理语言。
gawk [ POSIX or GNU style options ] -f program-file [ — ] file …
gawk [ POSIX or GNU style options ] [ — ] program-text file …
pgawk [ POSIX or GNU style options ] -f program-file [ — ] file …
pgawk [ POSIX or GNU style options ] [ — ] program-text file …
awk程序通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成。
program:通常使用单引号(’’)把{}引起来。
awk基本用法:
gawk [option] ‘program’ FILE…….
program:PATTERN{ACTION STATEMENTS} 语句之间用分号分隔;
选项:
-F:指明输入时用到的字段分隔符;默认以空白作为分隔符。
-v:var=value 自定义变量。
print: item=字段的意思。
(1)多个item之间使用“,”逗号分隔。
(2)输出的各item可以是字符,也可以是数值,变量或awk的表达式。
(3)如果省略item($1…)相当于print $0 整行的内容。
printf:可以调整文本的宽度,间隔等,比print功能要强。
分隔符、域和记录:
awk执行时,由分隔符分隔的字段(域)标记$1 $2 …..$n称为域标识。$0为所有域,代表整个文件。
注意:awk中的$符和shell中的$符含义是不同的。
文件的每一行称为记录。
省略action,则默认执行print $0 的操作。
awk的工作原理:
第一步:执行BEGIN{action;…..}语句块中的语句。
示例:
[root@centos6 Desktop]# awk 'BEGIN{print "hello world"}'
hello world
[root@centos6 Desktop]#
第二部:从文件或标准输入(stdin)读取一行,然后执行pattern{action;…..}语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
示例:
[root@centos6 Desktop]# awk -F: '{print "username:"$1”\t”"uid:"$3}' /etc/passwd
username:root uid:0
username:bin uid:1
username:daemon uid:2
username:adm uid:3
………………………………
[root@centos6 Desktop]#
第三部:当读取完文件时,执行END{action….}语句块。
BEGIN语句块在awk开始读取文件行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。
END语句块在awk读取完文件行之后被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选的语句块。
pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{print},即完整打印每一个读取到的行,awk读取到的每一行都会执行该语句块。
-v选项的变量:
(1)内建变量:input
FS:指明列分隔符,(类似于cut中的f),默认以空白字符作为分隔符。
[root@centos6 ~]# awk -v FS=":" '{print $1}' /etc/passwd
OFS:指明输出字段的分隔符,默认以空白字符作为分隔符。
[root@centos6 ~]# awk -v FS=":" -v OFS="=" '{print $1,$3,$6}' /etc/passwd
RS:指明换行分隔符,指定输入时的换行符,原换行符仍有效。
awk -v RS=" " '{print}' /etc/passwd
ORS:指明以什么代替回车换行符,输出时用指定的符号代替换行符。
awk -F: -v ORS="########" '{print $1,$2 }' /etc/passwd
root x##############bin x##############daemon x
NF:显示每行的字段总数。
1、
[root@centos6 Desktop]# awk -F: '{print NF}' /etc/passwd
7
7
7
……………………….
[root@centos6 Desktop]#
2、
[root@centos6 Desktop]# awk -F: '{print $(NF-6)}' /etc/passwd
root
bin
daemon
[root@centos6 Desktop]#
NR:显示行号。
1、
[root@centos6 Desktop]# awk -F: '{print NR,$1}' /etc/passwd
1 root
2 bin
3 daemon
4 adm
[root@centos6 Desktop]#
2、
[root@centos6 Desktop]# awk -F: END'{print NR,$1}' /etc/passwd
38 named
[root@centos6 Desktop]#
FNR:各文件分别计数,统计行号。
[root@centos6 Desktop]# awk '{print FNR, $0}' /etc/issue /etc/issue
1 CentOS release 6.8 (Final)
2 Kernel \r on an \m
3
1 CentOS release 6.8 (Final)
2 Kernel \r on an \m
3
[root@centos6 Desktop]#
FILENAME:显示当前文件名。
[root@centos6 Desktop]# awk '{print FILENAME, $0}' /etc/issue
/etc/issue CentOS release 6.8 (Final)
/etc/issue Kernel \r on an \m
/etc/issue
[root@centos6 Desktop]#
ARGC:显示命令行参数的个数。
[root@centos6 Desktop]# awk BEGIN'{print ARGC}' /etc/fstab /etc/issue
3
[root@centos6 Desktop]#
ARGV:数组,保存的是命令行所给定的各参数。
0、
[root@centos6 Desktop]# awk '{print ARGV[0]}' /etc/fstab /etc/issue
awk
1、
[root@centos6 Desktop]# awk '{print ARGV[1]}' /etc/fstab /etc/issue
/etc/fstab
2、
[root@centos6 Desktop]# awk '{print ARGV[2]}' /etc/fstab /etc/issue
/etc/issue
(2)自定义变量:
(1)-v var=value (变量名区分字符大小写)
(2)在program中直接定义
示例:
1、 [root@centos6 ]# awk -F: -v name=username '{print name,$1 }' /etc/passwd
username root
username bin
username daemon
………………………………..
2、[root@centos6 ]# awk -F: '{name="username";print name,$1}' /etc/passwd
username root
username bin
username daemon
………………………………..
printf命令:
格式化输出:printf “FORMAT”,item1,item2
(1)必须指定FORMAT。
(2)不会自动换行,需要显示给出换行控制符,\n。
(3)FORMAT中需要分别为后面每个item指定格式符。
格式符:与item一一对应:
%c:显示字符的ASCII码;
%d,%i:显示十进制整数;
%e,%E:显示科学计数法数值;
%f:显示为浮点数;
%g,%G:以科学计数法或浮点形式显示数值;
%s:显示字符串;
%u:无符号整数;
%%:显示%本身;
修饰符:
#[.#]:第一个数字控制显示的宽度,第二个#表示小数点后精度,例:%3.1f
–:左对齐(默认右对齐)%-10s
+:显示数值的正负符号%+10d
示例:
1、 以右对齐20个字打印/etc/passwd的第一个字段,以左对齐10个字符打印/etc/passwd的第二个字段。
[root@centos6 ]# awk -F: '{printf "%20s======== %-10d\n" ,$1,$2}' /etc/passwd
root======== 0
bin======== 0
daemon======== 0
adm======== 0
2、
[root@centos6 ]# awk -F: '{printf "nameuser:%-15s===== uid:%d\n",$1,$3}' /etc/passwd
nameuser:root ===== uid:0
nameuser:bin ===== uid:1
nameuser:daemon ===== uid:2
算数操作符:
+(加)、–(减)、*(乘)、/(除)、^(次幂)、%(取模运算)
示例:
[root@centos6 Desktop]# awk BEGIN'{print 10^10}'
10000000000
[root@centos6 Desktop]#
赋值操作符:
=、+=、-=、*=、/=、%=、%=、++、—
示例:
[root@centos6 ~]# awk -v i=1 BEGIN'{print i+=5}'
6
[root@centos6 ~]# awk -v i=1 BEGIN'{print i*=5}'
5
[root@centos6 ~]# awk -v i=10 BEGIN'{print i/=5}'
2
[root@centos6 ~]# awk -v i=10 BEGIN'{print i++}'
10
[root@centos6 ~]# awk -v i=10 BEGIN'{print ++i}'
11
[root@centos6 ~]# awk -v i=10 BEGIN'{print –i}'
9
[root@centos6 ~]# awk -v i=10 BEGIN'{print i++,i}'
10 11
[root@centos6 ~]#
比较操作符:
> 、>= 、< 、<=、!=、==
示例:
1、[root@centos6 ~]# awk -F: '$3<=2 {print $1}' /etc/passwd
root
bin
daemon
[root@centos6 ~]#
2、[root@centos6 ~]# awk -F: '$3>0 {print $1,$3}' /etc/passwd
3、[root@centos6 ~]# awk -F: '$3==0 {print $1}' /etc/passwd
root
[root@centos6 ~]#
4、[root@centos6 ~]# awk -F: '$3>0 && $3<5{print $1}' /etc/passwd
bin
daemon
adm
lp
[root@centos6 ~]#
模式匹配符:
~:左边匹配包含右边的全部显示出来;
!~:左边和右边不匹配的全部显示;
示例:
1、行中包括root字符的全部显示出来。
[root@centos6 ~]# awk '$0~"root"{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[ root@centos6 ~]#
2、除了上面两行显示的内容,都显示出来。
[root@centos6 ~]# awk '$0!~"root"{print $0}' /etc/passwd
3、在/etc/passwd中第一字段包含以root开头的显示出来。
[root@centos6 ~]# awk -F: '$1~"^root"{print $1}' /etc/passwd
root
[root@centos6 ~]#
逻辑操作符: 与&& 或|| 非!
示例:
1、[root@centos7 Desktop]# awk -F: '$3==0 || $3==1000{print $1}' /etc/passwd
root
zheng
[root@centos7 Desktop]#
2、[root@centos7 Desktop]# awk -F: '$3>0 && $3<=5{print $1}' /etc/passwd
bin
daemon
adm
lp
sync
[root@centos7 Desktop]#
3、[root@centos7 Desktop]# awk -F: '!($3>0){print $1}' /etc/passwd
root
[root@centos7 Desktop]#
条件表达式:(三目表达式):
selector?if-true-expression:if-false-xepression
示例:
[root@centos7]#awk-F:'$3>1000?username="commonuser":username="sysuser"{printf "%-20s %-10s===== %d\n",username, $1,$3}' /etc/passwd
awk pattern:
pattern:根据pattern条件,过滤匹配到的行,在做处理。
(1)如果未指定pattern:空模式,匹配每一行。
(2)/regular expression/:仅处理能够匹配到的行,需要用/ /括起来。
(3)/regular expression/:关系表达式,结果有“真”有“假”,结果为“真”才会被处理。
真:结果为非0值,非空字符串;
假:结果为空字符串或0值;
(4)line ranges:行范围。
startline,endline:/pattern1/,/pattern2/不支持直接给出数字格式。
(5)BEGINEND模式:
BEGIN{}:仅在开始处理文件中的文本之前执行一次。
END:仅在文本处理完成之后执行一次。
示例:
1、[root@centos7 Desktop]# awk '/^UUID/{printf "%s\n", $1}' /etc/fstab
UUID=2de5de7c-8ba6-4ce3-a56f-71ddc0e51765
UUID=fe32016e-a798-4b03-91a1-55adfd9a4355
UUID=f51b97fa-1ced-4ef0-9635-3d6d8f6feb5e
UUID=2bb4030e-68e8-4640-a3ac-62b98c029967
[root@centos7 Desktop]#
2、取反:[root@centos7 Desktop]# awk '!(/^UUID/){printf "%s\n", $0}' /etc/fstab
3、[root@centos7 Desktop]# awk '!0' /etc/passwd (为“真”可以打印/etc/passwd文件)
4、[root@centos7 Desktop]# awk '!1' /etc/passwd(为“假”不进行打印)
[root@centos7 Desktop]#
5、[root@centos7 Desktop]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
root /bin/bash
zheng /bin/bash
yibo /bin/bash
mage /bin/bash
[root@centos7 Desktop]#
示例:line ranges:行范围。
1、[root@centos7 Desktop]# awk -F: '/^root\>/,/^adm\>/{print $1}' /etc/passwd
root
bin
daemon
adm
[root@centos7 Desktop]#
2、[root@centos7 Desktop]# awk -F: 'NR>=10&&NR<=15{print $1}' /etc/passwd
operator
games
ftp
nobody
dbus
polkitd
[root@centos7 Desktop]#
示例:BEGIN/END模式:
[root@centos7 Desktop]# awk -F: 'BEGIN{print "username uid"}NR>=10&&NR<=20{printf "%-15s========= %-10d\n",$1,$3}END{print "end file"}' /etc/passwd
awk奇数偶数总结:
示例:
[root@centos7 Desktop]# seq 2 | awk 'i=0'
[root@centos7 Desktop]# seq 2 | awk 'i=1'
1
2
[root@centos7 Desktop]# seq 2 | awk 'i=!i'
1
[root@centos7 Desktop]# seq 2 | awk '!(i=!i)'
2
[root@centos7 Desktop]# seq 4 | awk '{i=!i;print i}'
1
0
1
0
[root@centos7 Desktop]#
使用awk取文件的奇数行:
示例:
[root@centos7 Desktop]# awk 'NR%2{print NR,$1}' /etc/fstab
1
3 #
5 #
7 #
9 UUID=2de5de7c-8ba6-4ce3-a56f-71ddc0e51765
11 UUID=f51b97fa-1ced-4ef0-9635-3d6d8f6feb5e
13 /dev/sdb1
[root@centos7 Desktop]#
使用awk取文件的偶数行:
示例:
[root@centos7 Desktop]# awk '!(NR%2){print NR,$1}' /etc/fstab
2 #
4 #
6 #
8 #
10 UUID=fe32016e-a798-4b03-91a1-55adfd9a4355
12 UUID=2bb4030e-68e8-4640-a3ac-62b98c029967
[root@centos7 Desktop]#
awk action:
常用的action分类:
(1)expressions:算术,比较表达式;
(2)control statements:if,while等;
(3)compound statements:组合语句;
(4)input statements
(5)output statement:print;
awk控制语句if-else
语法:{if(condition)statement [else statememt]}
{if(condition1){statement1}else if (condition2){statement2} else{statement3}}
示例:
1、查找/etc/passwd文件,如果$3是大于等于1000的行,然后打印$1、$3。
[root@centos7 ~]# awk -F: '{if($3>=1000){print $1,$3}}' /etc/passwd
nfsnobody 65534
zheng 1000
yibo 1001
mage 1002
[root@centos7 ~]#
2、查找/etc/passwd文件中,如果$7段中等于/bin/bash,然后打印$1S。
[root@centos7 ~]# awk -F: '{if($NF=="/bin/bash"){print $1}}' /etc/passwd
root
zheng
yibo
mage
[root@centos7 ~]#
3、查找出/etc/fstab文件中字段数大于5的行;
[root@centos7 ~]# awk '{if(NF>5){print $0}}' /etc/fstab
4、查找/etc/passwd文件中,如果$3大于等于1000,则打印common user并打印$1,否则打印root or sysuser 并打印$1。
[root@centos7 ~]# awk -F: '{if($3>=1000){printf "common user:%s\n",$1}else {printf "root or sysuser: %s\n",$1}}' /etc/passwd
5、使用awk中的if、else if、else判断语句:
awk -v test=100 'BEGIN{print test;if(test>90){print "very good"}else if(test>70){print "good"}else {print "no pass"}}' (因为代码后没有别的参数了,说以前面要执行BEGIN)
awk 控制语句while循环:
语法 {while(condition){statement}}
条件为“真”进入循环,条件“假”退出循环;
使用场景:
对行内的多个字段行逐一处理时使用;
对数组中的各元素逐一处理时使用;
示例:
1、使用while循环打印出/etc/grub2.cfg中的,以空格linux16开头的行的字段和字段的字符长度。
awk '/^[[:space:]]+linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg
2、使用while循环打印出/etc/grub2.cfg中的,以空格linux16开头的行的字段和字段的字符长度大于等于10的。
awk '/^[[:space:]]+linux16/{i=1;while(i<=NF){if(length($i)>=10)print $i,length($i);i++}}' /etc/grub2.cfg
awk控制语句do-while循环:
语法:do{statement}while(condition)
意义:无论真假,至少执行依次循环体。
示例:
1、使用do-while语句执行1加到100的sum。
awk 'BEGIN{sum=0;i=0;do{sum+=i;i++;print i,sum}while(i<=100){print sum}}'
2、测试执行命令花费的时间:
[root@centos7]# time awk 'BEGIN{sum=0;i=0;do{sum+=i;i++;print i,sum}while(i<=100){print sum}}'
awk 控制语句for循环:
语法:for(expr1;expr2;expr3){statement}
特殊用法:能够遍历数组中的元素;
示例:使用for循环打印出/etc/grub2.cfg中的,以空格linux16开头的行的字段和字段的字符长度。
awk '/^[[:space:]]+linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/grub2.cfg
性能比较:
可以使用time命令测试一条命令执行的时间长短:
示例:测试seq 1加到100所用的时间;
[root@centos7 Desktop]# time seq -s "+" 100 >> /dev/null |bc
real 0m0.006s
user 0m0.001s
sys 0m0.008s
[root@centos7 Desktop]#
awk 控制语句 switch语句:
语法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; …; default: statement}
break和continue以及next的用法:
示例:
1、计算100以内所有奇数的和。
awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0){continue}sum+=i;print sum}}'
2、计算1到50的和:
awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i>50){break}sum+=i;print sum}}'
3、打印/etc/passwd文件中的偶数行:
[root@centos7 Desktop]# awk -F: '{if($3%2!=0)next;print $1,$3}' /etc/passwd
awk数组:
(1)可以使用任意字符串,字符串要使用双引号括起来。
(2)如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空”。
(3)若要判断数组中是否存在某元素,要使用”index in array”格式进行遍历。
(4)若要遍历数组中的每个元素,要使用for循环。
示例:
1、创建数组并打印数组中的某个元素。
awk 'BEGIN{jiaotong["a"]="huoche";jiaotong["b"]="feiji";jiaotong["3"]="qiche";print jiaotong["3"]}'
2、去除文件中重复的行:
awk ‘!arr[$0]++’ file
3、遍历数组中的每个元素。
# awk 'BEGIN{jiaotong["a"]="huoche";jiaotong["b"]="feiji";jiaotong["3"]="qiche";print jiaotong["3"];for(i in jiaotong)print jiaotong[i]}'
qiche
huoche
feiji
qiche
[root@centos7 Desktop]#
4、查看文件中每行重复出现的次数。
[root@centos7 ~]# awk '{!stat[$0]++}END{for(i in stat)print i,stat[i]}' f1
aaaa 2
11111111 2
bbbbbbbbbb 2
cmslcml, 1
[root@centos7 ~]#
[root@centos7 ~]# cat f1 |uniq -c
2 aaaa
2 bbbbbbbbbb
2 11111111
1 cmslcml,
[root@centos7 ~]#
5、查看/var/log/httpd/access_log文件中IP地址链接的次数。
[root@centos6 Desktop]# awk '{stat[$1]++}END{for(i in stat)print i,stat[i]}' /var/log/httpd/access_log
10.1.252.238 3
[root@centos6 Desktop]#
awk '{line[$0]++}END{for(i in line)print i ,line[i]}' /etc/fstab
awk 函数:
数值处理:
rand():返回0和1之间一个随机数;
srand():随机数种子;
int:整数;
示例:
1、生成5个100以内随机的5个整数;
[root@centos7 ~]# awk 'BEGIN{srand();for(i=1;i<=5;i++)print int(rand()*100)}'
26
50
21
95
59
[root@centos7 ~]#
length():返回指定字符串的长度。
sub(r,s):搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s。
示例:sub只替换搜索到的第一个匹配的内容。
[root@centos7 ~]# echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-")'
2008-08:08 08:08:08
[root@centos7 ~]#
gsub(r,s):搜索r表示的模式匹配的内容,并全部替换为s所表示的内容。
示例:
[root@centos7 ~]# echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-")'
2008-08-08 08-08-08
[root@centos7 ~]#
split(s,array,“r”):以r代表分隔符,切割字符s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2………
示例:
[root@centos7 ~]# echo "2008:08:08 08:08:08" | awk 'split($0,num,":"){print num[1]}'
2008
[root@centos7 ~]# echo "2008:08:08 08:08:08" | awk 'split($0,num,":"){print num[3]}'
08 08
[root@centos7 ~]#
# netstat -tan | awk '/^tcp/{split($5,ip,":");print ip[1];counts[ip[1]]++}END{for(i in counts){print i ,counts[i] }}'
awk中调用shell命令:
system命令:
空格是awk中的字符串链接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用“”应用起来。
示例:
[root@centos7 ~]# awk 'BEGIN{system("hostname")}'
centos7
[root@centos7 ~]# awk 'BEGIN{test=100;system("echo " test)}'
100
[root@centos7 ~]#
awk脚本:
将awk程序写成脚本,直接调用执行。
[root@centos7 bin]# cat uid.awk
#!/bin/awk -f
#this is a awk scripts
{if($3>=1000)print $1,$3}
[root@centos7 bin]# uid.awk -F: /etc/passwd
nfsnobody 65534
zheng 1000
yibo 1001
mage 1002
[root@centos7 bin]#
向awk脚本中传递参数:
[root@centos7 bin]# cat uid.awk
#!/bin/awk -f
#this is a awk scripts
{if($3>=min && $3<=max)print $1,$3}
[root@centos7 bin]# uid.awk -F: min=100 max=200 /etc/passwd
usbmuxd 113
rtkit 172
qemu 107
abrt 173
avahi-autoipd 170
pulse 171
[root@centos7 bin]#
练习:
1、统计/etc/fstab文件中每个单词出现的次数:
[root@centos7 bin]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count){print i,count[i]}}' /etc/fstab
2、统计/etc/fstab文件中每个文件系统类型出现的次数:
[root@centos7 bin]# awk '/^UUID/{fs[$3]++}END{for(i in fs)print i,fs[i]}' /etc/fstab
swap 1
xfs 3
[root@centos7 bin]#
示例:
使用awk的“-F”选项指明以“:”作为列分隔符,取出/etc/passwd中第一个字段
[root@centos6 ~]# awk -F: '{print $1}' /etc/passwd
root
bin
daemon
adm
lp
……………………………….
[root@centos6 ~]#
使用awk的“-v”选项指明以“:”作为列分隔符,取出/etc/passwd中第一个字段
[root@centos6 ~]# awk -v FS=":" '{print $1}' /etc/passwd
root
bin
daemon
adm
lp
……………………………….
[root@centos6 ~]#
使用awk的“-v”选项指明以“:”作为列分隔符,输出时指定以“=”作为列分隔符,取出/etc/passwd中第一、第三、第六个字段等。
[root@centos6 ~]# awk -v FS=":" -v OFS="=" '{print $1,$3,$6}' /etc/passwd
root=0=/root
bin=1=/bin
daemon=2=/sbin
adm=3=/var/adm
lp=4=/var/spool/lpd
……………………………….
[root@centos6 ~]#
示例:
RS:指明行的换行分隔符,指定输入时的换行符,原换行符仍有效。
[root@centos6 ~]# awk -v RS=" " '{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP
User:/var/ftp:/sbin/nologin
……………………………….
[root@centos6 ~]#
原创文章,作者:zhengyibo,如若转载,请注明出处:http://www.178linux.com/49777