分页: 3 / 4

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-24 11:25
xiajing
fnan 写了:练习完了,就写个简单的sed多行处理:
sed -r ':a;N;$!ba;$s/(^[^x]*x|y[^y]*$)//g' file.txt
很精简!!!!!

问题是标记x和y是字符可以,如果希望保留第一个begin和最后一个end之间的内容,也就是说x字符换成begin字符串,y换成end字符串,那该怎么写更精简呢?
也许是我没有找到,也许是sed不支持 non greedy match,所以模拟non greedy match 花了3个sed命令。

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-24 12:10
我就是我2
可以使用grep

代码: 全选

grep -oP 'begin.*end' file.txt | sed -e 's/^begin//;s/end$//'
不必抓住sed不放.
不过, 处理单行可以,多行不行. :em20

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-24 13:26
jaszhou
多行文本处理用Perl才是王道,逻辑简单明了。

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-24 15:22
我就是我2
jaszhou 写了:多行文本处理用Perl才是王道,逻辑简单明了。
现在我不是不会么。如你所说的,我还在这折腾sed grep哦。 :em20
如果是perl,怎么写/? 请赐教。 :em06

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-24 15:46
xiajing
我就是我2 写了:可以使用grep

代码: 全选

grep -oP 'begin.*end' file.txt | sed -e 's/^begin//;s/end$//'
不必抓住sed不放.
不过, 处理单行可以,多行不行. :em20
的确用grep也可以, 思路是用grep的 -n 参数,找到第一个x的行数和最后一个y的行数(用shell的${parameter%%:*}提取行数),得到了两个行数,接着就可以用sed删除第一个行数前和第二个行数后的内容,然后对第一行和最后一行进行处理,不太实用,但可以当作练习。
jaszhou 写了:多行文本处理用Perl才是王道,逻辑简单明了。
赞成使用支持non-greedy match的"Practical Extraction and Report Language"

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-24 15:57
我就是我2
的确用grep也可以, 思路是用grep的 -n 参数,找到第一个x的行数和最后一个y的行数(用shell的${parameter%%:.*}提取行数),得到了两个行数,接着就可以用sed删除第一个行数前和第二个行数后的内容,然后对第一行和最后一行进行处理,不太实用,但可以当作练习。
这方法你也想得出来。 :em20
我最多想到前面说的
标记多行=>转成单行=>还原多行

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-24 21:05
fnan
xiajing 写了:
fnan 写了:练习完了,就写个简单的sed多行处理:
sed -r ':a;N;$!ba;$s/(^[^x]*x|y[^y]*$)//g' file.txt
很精简!!!!!

问题是标记x和y是字符可以,如果希望保留第一个begin和最后一个end之间的内容,也就是说x字符换成begin字符串,y换成end字符串,那该怎么写更精简呢?
也许是我没有找到,也许是sed不支持 non greedy match,所以模拟non greedy match 花了3个sed命令。
kose3@kose3-desktop:~$ cat f3.txt
dsojfdj
jdj begin dhfdkhbegin
jddk end1 dkjfij
ksdj end2 sjdkend3
djlk djkfl
kose3@kose3-desktop:~$ sed -r '/begin/!d;t;s/begin/&\n/;s/[^\n]*\n//;:a;N;$!ba;$s/(.*)end.*/\1/' f3.txt
dhfdkhbegin
jddk end1 dkjfij
ksdj end2 sjdk
kose3@kose3-desktop:~$
#可以啊,要分两次处理而已,还是只要一个进程。

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-24 21:55
我就是我2
虽然看了你的说明,感觉还是比较高级的东西.得回去参考一下手册. :em06
sed -r '/begin/!d;t;s/begin/&\n/;s/[^\n]*\n//;:a;N;$!ba;$s/(.*)end.*/\1/' f3.txt

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-25 4:10
fnan
这个逻辑很简单:

代码: 全选

sed -rn 's/begin/&\n/;T;           :j;N;$!bj;              $s/[^\n]*\n(.*)end.*/\1/p'  file.txt
       没有begin就读下一行     有begin就合并所有行        提取

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-25 14:26
jaszhou
我就是我2 写了:
jaszhou 写了:多行文本处理用Perl才是王道,逻辑简单明了。
现在我不是不会么。如你所说的,我还在这折腾sed grep哦。 :em20
如果是perl,怎么写/? 请赐教。 :em06
LZ可以参考这段代码:

------------------------------------------
#!/usr/bin/perl
use strict;

open (my $fh, 'text1.txt') or die "could not open";
open (my $out, '>t1.txt') or die "could not open";

undef $/;

my $line=<$fh>;

print $line;

if($line =~ /start(.*)end/s){
print $1;
print $out $1;
}

close ($fh) or die "error: could not close";
close ($out) or die "error: could not close";
---------------------------------------------------

输入文件text1.txt:

kljljlkjkkldf***start***dfd========start+++++sdfsdfsdfsdf
sdfdsfdfd+++++end======*****end*****sdfdfdsdfdsdfd

输出文件t1.txt:

***dfd========start+++++sdfsdfsdfsdf
sdfdsfdfd+++++end======*****

代码比sed清楚得多。LZ可以google一下具体的用法。

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-25 15:15
我就是我2
@jaszhou
说明一下
我不是LZ 不要看我发贴多,问题多我就是LZ了. :em20

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-25 18:11
fnan
jaszhou 写了:
我就是我2 写了:
jaszhou 写了:多行文本处理用Perl才是王道,逻辑简单明了。
现在我不是不会么。如你所说的,我还在这折腾sed grep哦。 :em20
如果是perl,怎么写/? 请赐教。 :em06
LZ可以参考这段代码:

------------------------------------------
#!/usr/bin/perl
use strict;

open (my $fh, 'text1.txt') or die "could not open";
open (my $out, '>t1.txt') or die "could not open";

undef $/;

my $line=<$fh>;

print $line;

if($line =~ /start(.*)end/s){
print $1;
print $out $1;
}

close ($fh) or die "error: could not close";
close ($out) or die "error: could not close";
---------------------------------------------------

输入文件text1.txt:

kljljlkjkkldf***start***dfd========start+++++sdfsdfsdfsdf
sdfdsfdfd+++++end======*****end*****sdfdfdsdfdsdfd

输出文件t1.txt:

***dfd========start+++++sdfsdfsdfsdf
sdfdsfdfd+++++end======*****

代码比sed清楚得多。LZ可以google一下具体的用法。
#不是吧,不能就一句吗?

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-25 22:13
horseinfly
手痒,也试试。
for i in *;do tr '\n' '@' <$i|awk -F"x" '{print $2}'|awk -F"y" '{print $1}' |tr '@' '\n'>$i-1.txt;done



想要一个shell 脚本 动作是:
1.依序读入一个文字档 tex1.txt ~ text9.txt:
tex1.txt 内容:
"abcxdefgaxcdyeafgxyxabefght..."
(文件是多行的
需要判断的关键字x y 可能是跨行)
2.删除档案中第1个x之前的内容(含x删除)

3.删除档案中最後一个y以後的内容(含y删除)

4.取得动作2 3 後所得档案 的 x 和 y 之间的文字 另存新档

得到 t1.txt ~ t9.txt

不知好心人可以帮忙一下吗?

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-25 22:42
我就是我2
手痒,也试试。
for i in *;do tr '\n' '@' <$i|awk -F"x" '{print $2}'|awk -F"y" '{print $1}' |tr '@' '\n'>$i-1.txt;done
:em20 跟我的思路一样的. 多行转化单行,再转化成多行.
分隔符是个大问题.你选的是@, 经过别人指点,我使用 \034

Re: 请问这样的Shell脚本如何写?

发表于 : 2011-08-26 19:14
fnan
我就是我2 写了:
手痒,也试试。
for i in *;do tr '\n' '@' <$i|awk -F"x" '{print $2}'|awk -F"y" '{print $1}' |tr '@' '\n'>$i-1.txt;done
:em20 跟我的思路一样的. 多行转化单行,再转化成多行.
分隔符是个大问题.你选的是@, 经过别人指点,我使用 \034
对,可见字符不可用!(命令没有测试吗?不能用的。)