84669 Lernen von Personen
152542 Lernen von Personen
20005 Lernen von Personen
5487 Lernen von Personen
7821 Lernen von Personen
359900 Lernen von Personen
3350 Lernen von Personen
180660 Lernen von Personen
48569 Lernen von Personen
18603 Lernen von Personen
40936 Lernen von Personen
1549 Lernen von Personen
1183 Lernen von Personen
32909 Lernen von Personen
如果第1行和第2行都不以;开头,则合并这两行为新行,并继续处理新行和第3行; 如果第1行以;开头,则继续处理第2行和第3行。 以上流程仅为方便描述,只要能达到相同效果即可。 如输入为: ;a ;;b c d; e;;; ;f g 期望输出: ;a ;;b cd;e;;; ;f g
学习是最好的投资!
awk '!/^;/{a=a$0}/^;/{if(a!="")print a;print $0;a="";}END{if(a!="")print a;}'
awk语法 test1{statements1}test2{statements2}...
test1{statements1}test2{statements2}...
针对每一行,如果满足test1,则执行statement1,如果满足test2,则执行statement2 ...
每一行
所以分3部分:
!/^;/{a=a$0}
;
a
!/^;/
!
/.../
^;
a=a$0
$0
a$0
/^;/{if(a!="")print a;print $0;a="";}
/^;/
if(a!="")print a;print $0;a="";
if(a!="")print a;
print $0;
a="";
END{if(a!="")print a;}
END
BEGIN
首先: 将换行符去掉,/\n//g 然后: 判断字母序列右侧是否有数字,有则在右侧添加换行符/([a-z]+)(?=[0-9]+)/\1\/n/g 判断字母序列左侧是否有数字,有则在左侧添加换行符/([a-z]+)(?<=[0-9]+)/\/n\1/g 最后: 将上面正则表达式用sed或者awk实现。
/\n//g
/([a-z]+)(?=[0-9]+)/\1\/n/g
/([a-z]+)(?<=[0-9]+)/\/n\1/g
sed
awk
awk版本
awk '$0 !~ /^;/{a=a$0;}/^;/{print a?a"\n"$0:$0;a=""}END{if(a)print a}' urfile
再附加一个sed的
sed -n '/^;/{H;x;s/^\n//g;p;s/.*//g;x;};/^;/!{H;x;s/\n//g;x};${/^;/!p}' urfile
这种略复杂的需求,用sed/awk是可以实现,但是我觉得不推荐,这时候一般用python或者perl来做更高效。
不过为了看看我的sed功底还在不在,还是尝试了一下,目前简单测试没有发现问题,代码如下:
sed -r -n '/^;/!{h;s/.*//;x;:l $!{H;n;/^;/!b l};x;s/\n//gp;g};p'
解释几个重点的部分: 1. h;s/.*//;x;是为了清空hold space 2. :l $!{H;n;/^;/!b l};部分是一个循环,将所有的非;开头的行合并到hold space,退出条件有两个:到达最后一行或者遇到一个;开头的行 3. x;s/\n//gp;g 将hold space中的内容去掉换行符并打印出来 4. 最后p打印pattern space中的内容,用来打印;开头的行
h;s/.*//;x;
:l $!{H;n;/^;/!b l};
x;s/\n//gp;g
p
答案还没写完,发现一个bug了: 如果文件的末尾有2行以上的非;开头的行,最后一行没有被合并。
修改一下原来的答案为:
sed -r -n '/^;/!{h;s/.*//;x;:l $!{H;n;/^;/!b l};/^;/!{H;g;s/\n//gp;t};x;s/\n//gp;g};p'
修改说明: 1. 跳出循环之后,判断当前行如果不是;开头(根据之前的跳出条件可知,这是最后一行),将当前行加入hold space,然后处理hold space的内容
看吧,一个其实也不是很复杂的需求,用sed来写,命令越写越长,1个月后还能一眼看懂么?这类需求还是不要用sed来做了吧
答案
解释
awk语法
test1{statements1}test2{statements2}...
针对
每一行
,如果满足test1,则执行statement1,如果满足test2,则执行statement2 ...所以分3部分:
!/^;/{a=a$0}
如果不以;
开头,则将当前行追加到临时变量a
(作为缓冲区)中!/^;/
!
否定/.../
表示测试当前行是否满足给定正则表达式^;
正则表达式,表示以;
开头a=a$0
a
变量,无需声明,直接使用,默认值是0、null、"",根据使用场景自动转换,这里第一次用就是空字符串$0
表示整个一行的内容a$0
两个字符串写在一起,表示字符串拼接/^;/{if(a!="")print a;print $0;a="";}
如果以;
开头,先输出临时拼接的变量a
(若有),再输出当前行/^;/
判断当前行是否以;
开头if(a!="")print a;print $0;a="";
if(a!="")print a;
如果a不为空,则输出a的值(print自动换行)print $0;
打印当前行a="";
清空a
的值,以备下次使用END{if(a!="")print a;}
处理完所有行,最后再判断缓冲区a
中是否有内容,若有,则打印;
开头,会全部追加到a
中,一直没有机会输出出来,因为碰到;
开头的行才会输出END
条件表示处理完最后一行之后(相对的当然有BEGIN
,表示处理第一行之前)首先: 将换行符去掉,
/\n//g
然后: 判断字母序列右侧是否有数字,有则在右侧添加换行符
/([a-z]+)(?=[0-9]+)/\1\/n/g
判断字母序列左侧是否有数字,有则在左侧添加换行符
/([a-z]+)(?<=[0-9]+)/\/n\1/g
最后: 将上面正则表达式用
sed
或者awk
实现。awk版本
再附加一个sed的
这种略复杂的需求,用sed/awk是可以实现,但是我觉得不推荐,这时候一般用python或者perl来做更高效。
不过为了看看我的sed功底还在不在,还是尝试了一下,目前简单测试没有发现问题,代码如下:
解释几个重点的部分:
1.
h;s/.*//;x;
是为了清空hold space2.
:l $!{H;n;/^;/!b l};
部分是一个循环,将所有的非;
开头的行合并到hold space,退出条件有两个:到达最后一行或者遇到一个;
开头的行3.
x;s/\n//gp;g
将hold space中的内容去掉换行符并打印出来4. 最后
p
打印pattern space中的内容,用来打印;
开头的行答案还没写完,发现一个bug了: 如果文件的末尾有2行以上的非
;
开头的行,最后一行没有被合并。修改一下原来的答案为:
修改说明:
1. 跳出循环之后,判断当前行如果不是
;
开头(根据之前的跳出条件可知,这是最后一行),将当前行加入hold space,然后处理hold space的内容看吧,一个其实也不是很复杂的需求,用sed来写,命令越写越长,1个月后还能一眼看懂么?这类需求还是不要用sed来做了吧