awk、sed、grep文本处理(七)

1、awk题 输出第二列重复的所有整行

awk题:如下文本内容
1 zhangsan
2 lisi
3 zhangsan
4 lisii
5 a
6 b
7 c
8 d
9 a
10 b
要求:输出第二列重复的所有整行,即输出结果:
1 zhangsan
3 zhangsan
5 a
9 a
6 b
10 b
awk '{a[$2]++;if(a[$2]==1){b[$2]=$0};if(a[$2]==2){print b[$2]"\n"$0}}' aaa


如果有重复2行以上的:
awk '{a[$2]++;if(a[$2]==1){b[$2]=$0};if(a[$2]==2){print b[$2]"\n"$0}else if(a[$2]>2){print $0}}' aaa | sort -t " " -k2

其他方法 (明天再整理整理 2020年8月30日23:38:15)

1、

for i in `awk '{print $2}' awk1.txt | awk 'a[$0]++'`; do grep -w $i awk1.txt ; done;

该方法有局限性,如果有3行重复的话。则不是想要的结果

2、

awk '{a[$2]++}END{for(i in a)if(a[i]>1){print i}}' awk1.txt  | xargs -i awk '/{}$/{print}' awk1.txt


前面出现两次及两次以上的内容,/{}$/ 的 $是锚定结尾
(本方法也适用于重复3条以上的数据)

3、

 

2、sed更换文本中的ip 和 port

需求:

答案:

文本内容:

<registrationlist>
        <registration id="128.195.52.5:8080">
                <fathergroup>console</fathergroup>
                <group>ntrf</group>
                <node>mSrv1</node>
                <ip>128.195.52.5</ip>
                <port>8080</port>
                <message>mSrv1</message>
                <needreg>yes</needreg>
        </registration>
</registrationlist>
ip=192.168.1.100
port=8088

#step 1 :
sed -r 's#(registration id=").*#\1'$ip':'$port'">#' ipTest.txt
#sed -r 's#(registration id=").*(">)#\1'$ip':'$port'\2#' ipTest.txt

#step 2 :
sed -r 's#(<ip>)(.*)(</ip>)#\1'$ip'\3#' ipTest.txt

#step 3 :
sed -r 's#(<port>)(.*)(</port>)#\1'$port'\3#' ipTest.txt


#step 2 和 step 3 合并写成一行
sed -r 's#(<ip>)(.*)(</ip>)#\1'$ip'\3#;s#(<port>)(.*)(</port>)#\1'$port'\3#' ipTest.txt



=========分割线=====
#如果单纯改端口: 将aaaaaa改成对应端口号即可
sed -r 's#(<registration id="([0-9]+.){3}[0-9]+:).*(">)#\1aaaaaaaaa\3#' test1.txt

本次问题,对分组,后向引用的运用又增加了一些。

另一个需求:

<endpoint id="console" type="http" uri="/ntrf" sec-node-id="108032" default="true">

uri="/ntrf" /ntrf 这个值怎么改掉
uri="/ntrf" 比如变成 uri="/1234"

sec-node-id="108032"  108032 这个值怎么改掉
sec-node-id="108032" 比如变成 sec-node-id="1234"

 

3、获得当月的最后一 天  

1、
cal | grep -Poz '\d+(?=\s*$)'
(注意grep的版本,如果是低版本, -z没效果)

2、
cal | perl -0anE'}{say pop@F'

3、
cal | awk 'NR==7{print $NF}'

4、
date -d "-$(date +%d) days +1 month" +%d

5、
date -d "$(date +%Y-%m-01) -1 day +1 month" +"%d"

4、符合条件的打印出来,不符合则打印err

1、
awk '{print ($NF>2?$NF:"err")}' 1.txt

2、
awk '{if($NF>2"")print $NF;else print "err"}' 1.txt

3、
perl -lne 'if(/(?<=dog\s)\d+/){if($&>2){print $&}else{print "err"}}' 1.txt

(perl是没学过,但他是用零宽断言取最后的数字,然后做if判断)

5、将数据拼接insert语句

Gates Bill Xuanwumen 10 Beijing
Carter  Thomas  Changan Street  Beijing
张 三丰 樱花 路 某某市
李 斯   武鸣 xx市区
1、自己写的 (写固定了,有局限性)
sed -r "s#(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)#INSERT INTO Persons VALUES ('\1','\2','\3 \4','\5')#" insert.txt

大佬给的建议是:两三个替换组合在一起也行,^替换成你那一长串字符,每个单词结尾替换成',',末尾替换成'),肯定是可以的,而且可以帮sed绕开每列不固定的问题。
三个替换写在一起就行了:开头,中间,结尾 写三个替换s###;s###g;s###


2、大佬写的perl (很强)
perl -anE'say"INSERT INTO Persons VALUES (\x27".join("\x27,\x27",@F)."\x27)"' insert.txt

效果:

晚上根据大佬给的思路,写出的对应的指令:

sed -r "s#(\w+)\s#\1','#g;s#(\w+$)#\1')#;s#^(\w+)#INSERT INTO Persons VALUES ('\1#g" test
顺序是 末尾 -> 中间 -> 开头

最开始是 开头-> 中间-> 末尾。 这样有问题,第二个 s### 。把开头第一个 添加的字符串也加上 ','


=============
sed -r "s#^(\w+)\s+#INSERT INTO Persons VALUES ('\1','#g" test --开头
sed -r "s#(\w+)\s#\1','#g" test  中间单词
sed -r "s#(\w+$)#\1')#g" test     --末尾

写法2

最开始的写法(但结果有误):

other:

[A-z]会匹配[,\,],^,-,`这6个字符,加个大小写字母,一共58个字符,不是52个各位尽量少用,尤其是如果文本内容很多,自己没办法概览全文的时候。加这6个字符其实是有意义的,也不是随便乱想

sed追加内容

2>/dev/null 可去掉下图红框的提示

取path的值:

<?xml version="1.0" encoding="UTF-8"?>

-
<FUSE xsi:noNamespaceSchemaLocation="../../schemas/sra-fuser.v2.xsd"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2018-01-22">
    <File timestamp="2017-11-28T01:56:57" path="http://ftp-trace.ncbi.nlm.nih.gov/blast/db/cloud/2018-01-22/nr.00.phd" size="146765" name="nr.00.phd"/>
    <File timestamp="2017-11-28T01:56:57" path="http://ftp-trace.ncbi.nlm.nih.gov/blast/db/cloud/2018-01-22/nr.00.phi" size="3504" name="nr.00.phi"/>
1、
grep -oP '(?<=path=").*?(?=")' test1.txt

2、
grep -oP '(?<=path=")[^"]+' test1.txt

3、
grep -oP 'path="\K[^"]+' test1.txt

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值