如何配对儿

sh/bash/dash/ksh/zsh等Shell脚本
回复
悬崖勒马2011
帖子: 91
注册时间: 2013-01-23 14:27
系统: ubuntu 12.04

如何配对儿

#1

帖子 悬崖勒马2011 » 2014-04-22 18:48

一个文件有如下数据(每一行一个数): 1.1 1.3 3.1 3.5 4.4 6.3 6.9 9.0
我想实现一个这样的目的:当两数之差小于1配为一对儿,大于1则单独抽出来自己和自己配对儿。例如 1.1 1.3 , 3.1 3.5 ,6.3 6.9为三对儿,4.4 和9.0 自己各为“一对儿”。
该如何写??
上次由 悬崖勒马2011 在 2014-04-22 19:45,总共编辑 1 次。
cao627
帖子: 992
注册时间: 2007-12-05 10:57
系统: ubuntu14.04
来自: 金山

Re: 如何配对儿

#2

帖子 cao627 » 2014-04-22 19:27

4.4 5.3为什么不一对,不是相差0.9吗
悬崖勒马2011
帖子: 91
注册时间: 2013-01-23 14:27
系统: ubuntu 12.04

Re: 如何配对儿

#3

帖子 悬崖勒马2011 » 2014-04-22 19:45

cao627 写了:4.4 5.3为什么不一对,不是相差0.9吗
不好意思,我又改了一下。
cao627
帖子: 992
注册时间: 2007-12-05 10:57
系统: ubuntu14.04
来自: 金山

Re: 如何配对儿

#4

帖子 cao627 » 2014-04-22 20:28

所谓两数之差是不是相邻两行的数?如果是的话:
awk

代码: 全选

$ awk '{if(a){if($1-a < 1){print a" "$1;a="";next}else{print a;a=$1}}else{a=$1}}END{print $1}' file
悬崖勒马2011
帖子: 91
注册时间: 2013-01-23 14:27
系统: ubuntu 12.04

Re: 如何配对儿

#5

帖子 悬崖勒马2011 » 2014-04-22 20:50

cao627 写了:所谓两数之差是不是相邻两行的数?如果是的话:
awk

代码: 全选

$ awk '{if(a){if($1-a < 1){print a" "$1;a="";next}else{print a;a=$1}}else{a=$1}}END{print $1}' file
我自己写了个脚本,用来输出一共有多少对:

NR=`cat x.cat | wc -l`
i=1
n=0
while [ `echo "$i <= $NR " | bc` == 1 ]
do
j=`echo $i+1 | bc `
a=`cat 3 | sed -n ${i}p`
b=`cat 3 | sed -n ${j}p`
c=`echo "scale=2;$b-$a" | bc `

if [ `echo "$c < 1"|bc` == 1 ] ; then
n=$(($n+1))
i=$(($i+2))
else
n=$(($n+1))
i=$(($i+1))
fi

done
echo $n
cao627
帖子: 992
注册时间: 2007-12-05 10:57
系统: ubuntu14.04
来自: 金山

Re: 如何配对儿

#6

帖子 cao627 » 2014-04-22 22:32

while [ `echo "$i <= $NR " | bc` == 1 ]
为什么不直接while [ $i -le $NR ]
同理
if [ `echo "$c < 1"|bc` == 1 ]
可直接if [ $c -lt 1 ]

还有是否有必要给两数之差加上绝对值?
比如 3 - 1 == 2 > 1 一和三是两对。而 1 - 3 == -1< 1 一和三又是一对?
如果这样的话4搂的awk中 $1-a < 1也要换成 ($1-a)^2 < 1

还有,既然n=$(($n+1))在if的两分支中都有,那么它就和if判断的真假无关了,所以可以直接写一条,在if语句前面或后面。
头像
YeLee
论坛版主
帖子: 26406
注册时间: 2008-08-13 8:48
系统: Fundu i64
来自: 东海硇州,一双管钥。
联系:

Re: 如何配对儿

#7

帖子 YeLee » 2014-04-22 23:14

看这说话风格,莫非阁下是北京人? :em04
◎当我站在道德的高度上俯视别人的时候,发现自己是多么渺小。
♥执着但不偏激,反对而不排斥,坚决捍卫矛盾体的存在方式。
★★★天气预报★★★
fcitx-yatable一个可以使用的码表输入法
[教程]几个实例攻克软件编译难关
Gentoo Development Guide
字体相关
头像
astolia
论坛版主
帖子: 6703
注册时间: 2008-09-18 13:11

Re: 如何配对儿

#8

帖子 astolia » 2014-04-23 0:19

如果只输出有几对问题就清楚多了,另外1楼没说清楚差值刚好等于1时是否配对,就按5楼的代码当成不能配对好了

1楼也没说文件里的数据是否保证升序排列,为保险起见就先排个序好了

代码: 全选

#!/bin/bash -

n=0
p=""
while read x; do
	if [[ -z "$p" ]]; then
		p="$x"
	elif [[ $(echo "$x - $p < 1" | bc) == "1" ]]; then
		((n++))
		p=""
	else
		((n++))
		p="$x"
	fi
done < <(sort x.txt)

if [[ -n "$p" ]]; then
	((n++))
fi

echo "$n"
上次由 astolia 在 2014-04-23 0:35,总共编辑 1 次。
头像
astolia
论坛版主
帖子: 6703
注册时间: 2008-09-18 13:11

Re: 如何配对儿

#9

帖子 astolia » 2014-04-23 0:24

cao627 写了:
if [ `echo "$c < 1"|bc` == 1 ]
可直接if [ $c -lt 1 ]
[和bash的[[都只处理整数的,算浮点数还是要用bc

代码: 全选

$ [ "1.1" -gt "1" ]
bash: [: 1.1: integer expression expected
$ [[ "1.1" -gt "1" ]]
bash: [[: 1.1: syntax error: invalid arithmetic operator (error token is ".1")
cao627
帖子: 992
注册时间: 2007-12-05 10:57
系统: ubuntu14.04
来自: 金山

Re: 如何配对儿

#10

帖子 cao627 » 2014-04-23 9:38

[和bash的[[都只处理整数的,算浮点数还是要用bc
是的
可以这样
if [ [ (( $c < 1 )) ] ]
头像
bzhao
帖子: 252
注册时间: 2008-07-05 2:15
系统: XUbuntu

Re: 如何配对儿

#11

帖子 bzhao » 2014-06-16 21:29

代码: 全选

#!/bin/sh

count=0
#
while read line
do
    ((count++))
    if [ $count -eq 2 ] && [ x$(echo "($line-$pre_line)<1"|bc) = x1 ] ; then
        echo $pre_line:$line
        count=0
    elif [ $count -eq 2 ]; then
        echo $pre_line:$pre_line
        count=1
    else
        :
    fi
    pre_line=$line
# echo $count
done <aaa.txt
 
if [ $count -eq 1 ]; then
    echo $pre_line:$pre_line
fi
Bill Z
stat -c %a filename
\_.\{-}
回复