2011-04-19 87 views
2

我有一个bash脚本输出一些基于列的信息。我想给用户一些匹配值的选项是特定的列。例如,./myColumnDump可能会打印基于Bash中的列值过滤行

 
User Job_name Start_day 
andrew job1_id monday 
andrew job2_id tuesday 
adam job1_id tuesday 
adam job2_id monday 

,我想补充像./myColumDump -j 2选项(其中的J的说法是使用正则表达式匹配,其在JOB_NAME列中的值)。

我目前正在通过grep管道输出,并将用户指定的正则表达式嵌入到一个大正则表达式中以匹配整行,但是他/她可能会指定-j .*monday这将溢出到不同的列中。

有没有更好的方法来实现这个在bash脚本?

回答

2

下面是完整的bash脚本scan.sh做你的工作:

#!/bin/bash 
usage() 
{ 
cat << EOF 
usage: $0 options 
This script scans given input file for specified regex in the input column # 
OPTIONS: 
    -h  Show usage instructions 
    -f  input data file name 
    -r  regular expression to match 
    -j  column number 
EOF 
} 
# process inputs to the script 
DATA_FILE= 
COL_NUM= 
REG_EX= 
while getopts ":j:f:r:h" OPTION 
do 
    case $OPTION in 
     f) DATA_FILE="$OPTARG" ;; 
     r) REG_EX="$OPTARG" ;; 
     j) COL_NUM="$OPTARG" ;; 
     \?) usage 
      exit 1 ;; 
     h) 
      usage 
      exit 1 ;; 
    esac 
done 
if [[ -z $DATA_FILE ]] || [[ -z $COL_NUM ]] || [[ -z $REG_EX ]] 
then 
    usage 
    exit 1 
fi 

awk -v J=${COL_NUM} -v R="${REG_EX}" '{if (match($J, R)) print $0;}' "${DATA_FILE}" 

测试

比方说,这是你的数据文件: 用户JOB_NAME START_DAY

andrew job1_id monday 
andrew job2_id tuesday 
adam job1_id tuesday 
adam job2_id monday 

./scan.sh -j 2 -f data -r ".*job1.*" 
andrew job1_id monday 
adam job1_id tuesday 

./scan.sh -j 2 -f data -r ".*job2.*" 
andrew job2_id monday 
adam job2_id tuesday 

./scan.sh -j 1 -f data -r ".*adam.*" 
adam job1_id tuesday 
adam job2_id monday 
2

此问题是为awk(1)量身定做的。例如,您可以执行以下操作:

awk '$2 ~ /^job1/' 

可打印出第2列匹配的行^job1。因此,鉴于N列数和R正则表达式,你应该能够做到这一点:

awk "\$${N} ~ /${R}/" 

你会像往常一样,需要小心你的报价。

2

要建立在亩太短的回答,您可以将用户的模式传递给AWK:

# suppose the -j pattern is in shell var $j 
awk -v j="$j" '$2 ~ j' 

不得不提醒用户输入了awk理解虽然正则表达式。

2

这里的一个纯粹的bash脚本(礼貌anubhava)

#!/bin/bash 
# tested on bash 4 
usage() 
{ 
cat << EOF 
usage: $0 options [file] 
This script scans given input file for specified regex in the input column # 
OPTIONS: 
    -h  Show usage instructions 
    -f  input data file name 
    -r  regular expression to match 
    -j  column number 

Example: $0 -j 2 -r "job2" -f file 
EOF 
} 
# process inputs to the script 
DATA_FILE= 
COL_NUM= 
REG_EX= 
while getopts ":j:f:r:h" OPTION 
do 
    case $OPTION in 
     f) DATA_FILE="$OPTARG" ;; 
     r) REG_EX="$OPTARG" ;; 
     j) COL_NUM="$OPTARG" ;; 
     \?) usage 
      exit 1 ;; 
     h) 
      usage 
      exit 1 ;; 
    esac 
done 
if [[ -z $DATA_FILE ]] || [[ -z $COL_NUM ]] || [[ -z $REG_EX ]] 
then 
    usage 
    exit 1 
fi 
while read -r line 
do 
    array=($line) 
    col=${array[$((COL_NUM-1))]} 
    [[ $col =~ $REG_EX ]] && echo "$line" 
done < $DATA_FILE