2011-04-19 84 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