Chinaunix

标题: 这种情况下的字符过滤如何处理呢? [打印本页]

作者: bkj    时间: 2007-12-24 15:37
标题: 这种情况下的字符过滤如何处理呢?
统计原则:分别统计a-t的字母个数,要求每条记录至少5个字母,最多10个字母,且字母在a-t之间惟一。如果记录中存在数字则丢弃该条记录,但是每个字母用,;。:等符号隔开应视为有效记录;
同时满足上述条件的行,如果行里的内容是相同的也为正常记录,不应该过滤掉。

abcd
Abcde
Abcde
Abcdex
Abcde0
Abcdefghijk
aAbBcCdDeEf
a,b,c,d,e,f
aAbAcAdAe
ABCDEabcde
过滤结果为

Abcde
Abcde
Abcdefghijk
a,b,c,d,e,f
作者: bkj    时间: 2007-12-24 15:57
请大家帮忙看看
作者: BLZer    时间: 2007-12-24 16:50
原帖由 bkj 于 2007-12-24 15:37 发表
统计原则:分别统计a-t的字母个数,要求每条记录至少5个字母,最多10个字母,且字母在a-t之间惟一。如果记录中存在数字则丢弃该条记录,但是每个字母用,;。:等符号隔开应视为有效记录;
同时满足上述条件的行 ...

#!/bin/bash

FILE=~/shell/sed/cu28.txt #数据文件

while read LINE ; do
#将标点符号去掉,并将大写转成小写
TEMP=$(echo $LINE | sed 's/,//g' | tr [:upper:] [:lower:])
NUM=${#TEMP}
#转换为小写字母
CON=0
if [ ${#TEMP} -ge 5 ] && [ ${#TEMP} -le 10 ]    #只有在5-10个字符的才去判断
then
    if [ ! $(echo $TEMP | grep "[0-9U-Zu-z]" ] #不包含数字和u-z字母的才判断
    then
        #这两个for循环判断变量内有无相同的字符,如有,则将CON值设置为1,
        for((i = 0 ; i <= $NUM -1 ; i++))
        do
        TEMP1=${TEMP{i}:1}
            for ((j = i+1 ; j <= $NUM-1 ; j++)) ; do
                TEMP2=${TEMP{j}:1}
                if [ ${TEMP1} = ${TEMP2} ] ;  then
                CON=1
                fi
            done
        done
        #如果CON值为止。打印变量
        if [ ${CON} -eq 0 ] ; then
            echo $LINE
        fi
    fi
fi
done <${FILE}

作者: frankytf    时间: 2007-12-24 16:53
[code]grep -v "[0-9]" test.txt|awk '{a=length();if(a>4&&a<10) print ;}'[\code]

但是每个字母用,;。:等符号隔开应视为有效记录; 不理解
作者: bkj    时间: 2007-12-24 19:35
语法错误

root# d.sh
./d.sh: line 11: syntax error near unexpected token `for(('
./d.sh: line 11: `       for((i = 0 ; i <= $NUM -1 ; i++)) '

root# more d.sh
#!/bin/bash
file=/tmp/test1.txt
while read LINE ; do
TEMP=$(echo $LINE | sed 's/,//g' | tr [:upper:] [:lower:])
NUM=${#TEMP}
CON=0
if [ ${#TEMP} -ge 5 ] && [ ${#TEMP} -le 10 ]
then
    if [ ! $(echo $TEMP | grep "[0-9U-Zu-z]" ]
    then
       for((i = 0 ; i <= $NUM -1 ; i++))
        do
        TEMP1=${TEMP{i}:1}
        for ((j = i+1 ; j <= $NUM-1 ; j++)) ;
        do
        TEMP2=${TEMP{j}:1}
        if [ ${TEMP1} = ${TEMP2} ] ;  
        then
        CON=1
        fi
        done
        done
        if [ ${CON} -eq 0 ] ; then
        echo $LINE
        fi
        fi
fi
done <${FILE}
作者: bkj    时间: 2007-12-24 19:37
原帖由 frankytf 于 2007-12-24 16:53 发表
grep -v "[0-9]" test.txt|awk '{a=length();if(a>4&&a


这种做法没有考虑到过滤每行重复的字符,需要将包含重复的字符的行过滤掉,而且大小写不敏感。
作者: r2007    时间: 2007-12-24 19:45
没数错的话,Abcdefghijk是11个字母吧?为何是正常记录?
作者: bkj    时间: 2007-12-24 20:05
原帖由 r2007 于 2007-12-24 19:45 发表
没数错的话,Abcdefghijk是11个字母吧?为何是正常记录?


楼上的说得对,这行是要过滤掉的。
作者: r2007    时间: 2007-12-24 20:15
刚要做,又发现疑问,这两个违反那条了?
aAbAcAdAe
ABCDEabcde
作者: bkj    时间: 2007-12-24 20:20
原帖由 r2007 于 2007-12-24 20:15 发表
刚要做,又发现疑问,这两个违反那条了?
aAbAcAdAe
ABCDEabcde


出现了重复字符,因为大小写不敏感
作者: r2007    时间: 2007-12-24 20:39
不知道理解了题意没有^_^
  1. sed -n '/[0-9]/d;h;y/ABCDEFGHIJKLMNOPQRST/abcdefghijklmnopqrst/;/\([a-t]\).*\1/d;s/[^a-t]//g;/^.\{5,10\}$/{g;p}'
复制代码

btw:
xyzabc
a b c d e f
a@b#c%d*e
这些如何处理?
作者: Cion    时间: 2007-12-24 21:28
标题: 回复 #3 BLZer 的帖子
仅仅这种编码风格,不用看内容,看看缩进和适时的注释,就值得我们称赞了!
作者: springwind426    时间: 2007-12-24 21:30

  1. perl -e 'while(<>){
  2. next if /[0-9]/;
  3. $a=$_;
  4. chomp;
  5. $_=lc;
  6. next if /[u-z]/;
  7. s/[^a-t]//g;
  8. print $a if !/([a-t]).*\1/ && m/^.{5,10}$/}' <数据文件
复制代码


思路:
行中出现数字,就不符合要求
转换成小写后,如果出现[u-z]则不符合要求(如果行中还可能出现其他的不符合要求的字符,可以罗列在[u-z]中)
把除[a-t] 之外的字符删除,如果字符数在5~10,并且没有重复字符的话,就打印原始的数据。
作者: bkj    时间: 2007-12-24 21:57
谢谢楼上的帮助
PS.用shell脚本好实现吗?
作者: ArchieYao    时间: 2007-12-25 02:13
原帖由 r2007 于 2007-12-24 20:39 发表
不知道理解了题意没有^_^
sed -n '/[0-9]/d;h;y/ABCDEFGHIJKLMNOPQRST/abcdefghijklmnopqrst/;/\([a-t]\).*\1/d;s/[^a-t]//g;/^.\{5,10\}$/{g;p}'
btw:
xyzabc
a b c d e f
a@b#c%d*e
这些如何处理?


这个挺强,按楼主的意思把 u-z 的过滤就好了
作者: springwind426    时间: 2007-12-25 09:16
原帖由 bkj 于 2007-12-24 21:57 发表
谢谢楼上的帮助
PS.用shell脚本好实现吗?


  1. #!/bin/bash
  2. while read line
  3. do
  4.         tmp=$(echo "$line" | tr 'A-Z' 'a-z')   # 转换小写
  5.         tmp="${tmp/[0-9u-z]}"  
  6.         [ ${#line} -ne ${#tmp} ] && continue  #判断是否有非法字符
  7.         tmp="${tmp//[^a-t]}"  #提取有效字符
  8.         [ ${#tmp} -lt 5 -o ${#tmp} -gt 10 ] && continue;  #判断是否是合法长度
  9.         echo "${tmp}" | grep -qE '(.).*\1'   #判断是否有重复字符
  10.         [ $? -ne 0 ] && echo "${line}"
  11. done  < 数据文件
复制代码

作者: pheobee    时间: 2007-12-25 14:55
楼主说大小写不敏感,没说大写转小写吧。
作者: springwind426    时间: 2007-12-25 15:13
原帖由 pheobee 于 2007-12-25 14:55 发表
楼主说大小写不敏感,没说大写转小写吧。



转换成小写比较好处理

不过,实际显示的仍然是原来的内容
作者: pheobee    时间: 2007-12-25 15:27
原帖由 springwind426 于 2007-12-25 15:13 发表



转换成小写比较好处理

不过,实际显示的仍然是原来的内容


呵呵。试了,果然好用。学习了。
作者: bkj    时间: 2007-12-25 16:49
执行楼上的脚本时怎么会抱错呢?

root@# sh f.sh
f.sh: syntax error at line 4: `tmp=$' unexpected
root@# more f.sh
#!/bin/bash
while read line
do
        tmp=$(echo "$line" | tr 'A-Z' 'a-z')   # 转换小写
        tmp="${tmp/[0-9u-z]}"  
        [ ${#line} -ne ${#tmp} ] && continue  #判断是否有非法字符
        tmp="${tmp//[^a-t]}"  #提取有效字符
        [ ${#tmp} -lt 5 -o ${#tmp} -gt 10 ] && continue;  #判断是否是合法长度
        echo "${tmp}" | grep -qE '(.).*\1'   #判断是否有重复字符
        [ $? -ne 0 ] && echo "${line}"
done <test1.txt
作者: springwind426    时间: 2007-12-25 20:11
这个是需要bash支持的
你先看看你的系统中bash是否在/bin/目录下
可以用which bash来查找bash所在的具体位置,然后将#!/bin/bash修改成实际的路径

然后将这个文件修改成可执行
chmod +x f.sh

直接运行 ./f.sh

或者用
bash f.sh
看看
作者: bkj    时间: 2007-12-27 01:26
bash的路径没问题,但是执行时还是有问题。

root@sun # which bash
/bin/bash
root@sun # more f.sh
#!/bin/bash
while read line
do
        tmp=$(echo "$line" | tr 'A-Z' 'a-z')
        tmp="${tmp/[0-9u-z]}"  
        [ ${#line} -ne ${#tmp} ] && continue
        tmp="${tmp//[^a-t]}"  #??????
        [ ${#tmp} -lt 5 -o ${#tmp} -gt 10 ] && continue;
        echo "${tmp}" | grep -qE '(.).*\1'
        [ $? -ne 0 ] && echo "${line}"
done < test1.txt
root@sun # ./f.sh
grep: illegal option -- q
grep: illegal option -- E
Usage: grep -hblcnsviw pattern file . . .
sbemg
grep: illegal option -- q
grep: illegal option -- E
Usage: grep -hblcnsviw pattern file . . .
sbeml
grep: illegal option -- q
grep: illegal option -- E
Usage: grep -hblcnsviw pattern file . . .
sbeml
grep: illegal option -- q
grep: illegal option -- E
Usage: grep -hblcnsviw pattern file . . .
sbeml
grep: illegal option -- q
grep: illegal option -- E
Usage: grep -hblcnsviw pattern file . . .
sbeml
grep: illegal option -- q
grep: illegal option -- E
Usage: grep -hblcnsviw pattern file . . .
sbeml
grep: illegal option -- q
grep: illegal option -- E
Usage: grep -hblcnsviw pattern file . . .
sbeml
grep: illegal option -- q
grep: illegal option -- E
Usage: grep -hblcnsviw pattern file . . .
sbeml
grep: illegal option -- q
grep: illegal option -- E
Usage: grep -hblcnsviw pattern file . . .
tnjkm
作者: bkj    时间: 2007-12-27 01:27
还请指点一下问题在哪里呢?
作者: springwind426    时间: 2007-12-27 08:06
grep 的版本?

它似乎不支持 -q 和 -E


  1.         echo "${tmp}" | grep -qE '(.).*\1'
  2.         [ $? -ne 0 ] && echo "${line}"
复制代码


修改成

  1.    tmp1=$(echo "${tmp}" | sed 's/\(.\).*\1//')
  2.    [ ${#tmp} -eq ${#tmp1} ] && echo "${line}"
复制代码

试试
作者: bkj    时间: 2007-12-27 14:19
root@sun # more g.sh
#!/bin/bash
while read line
do
        tmp=$(echo "$line" | tr 'A-Z' 'a-z')
        tmp="${tmp/[0-9u-z]}"  
        [ ${#line} -ne ${#tmp} ] && continue
        tmp="${tmp//[^a-t]}"
        [ ${#tmp} -lt 5 -o ${#tmp} -gt 10 ] && continue;
         tmp1=$(echo "${tmp}" | sed 's/\(.\).*\1//')
         [ ${#tmp} -eq ${#tmp1} ] && echo "${line}"
done < test1.txt
root@sun # more test1.txt
bcd
Abcde
Abcde
Abcdex
Abcde0
Abcdefghijk
aAbBcCdDeEf
a,b,c,d,e,f
aAbAcAdAe
ABCDEabcde
M,A,D,H,P,
M,A,D,H,P,
OTDHA
OCEAH
root@sun # ./g.sh
Abcde
Abcde
a,b,c,d,e,f

正确的结果应该为:
Abcde
Abcde
a,b,c,d,e,f
M,A,D,H,P,
M,A,D,H,P,
OTDHA
OCEAH

统计原则:分别统计a-t的字母个数且不区分大小写,要求每条记录至少5个字母,最多10个字母,且字母在a-t之间惟一。如果记录中存在数字则丢弃该条记录,但是每个字母用,;。:等符号隔开应视为有效记录;
同时满足上述条件的行,如果行里的内容是相同的也为正常记录,不应该过滤掉。
作者: bkj    时间: 2007-12-27 14:20
修改后的脚本,运行的结果有问题,具体见上一次回复
作者: springwind426    时间: 2007-12-27 15:31
建议:

不知道你的运行环境,你可以在上面脚本的每个处理并赋值的语句后面用echo把它显示出处理结果,看看问题出现在什么地方

可以在test1.txt文件中只添加几个有特殊的行,这样可以减少干扰。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2