bash grep -e到循环中的数组

时间:2016-08-21 11:38:29

标签: bash grep

我有一个重复数据模式的文本,grep不停地获取所有匹配。

for ((count = 1; count !=17; count++)); do       # 17 times 
 xuz1[count]=`grep -e "1  O1" $out_file | cut -c10-29`    
 xuz2[count]=`grep -e "2  O2" $out_file | cut -c10-29`
 xuz3[count]=`grep -e "3  O3" $out_file | cut -c10-29`

 echo ${xuz1[count]}
 echo ${xuz2[count]}
 echo ${xuz3[count]}
done

数据如下:

some text.....
Text....
 .....
1  O1    111111 111111 111111
2  O2    222211 222211 222211
3  O3    643653 652346 757686
some text.....
1  O1    111122 111122 111122
2  O2    222222 222222 222222
3  O3    343653 652346 757683
some text.....
1  O1    111333 111333 111333
2  O2    222333 222333 222333
3  O3    343653 652346 757684
.
.
.

结果我得到了:

  xuz1[1] = 111111 111111 111111  
  xuz2[1] = 222211 222211 222211 
  xuz3[1] = 643653 652346 757686

  xuz1[2] = 111111 111111 111111  
  xuz2[2] = 222211 222211 222211 
  xuz3[2] = 643653 652346 757686        

...

寻找这样的结果:

 xuz1[1]=111111 111111 111111 
 xuz2[1]=222211 222211 222211
 xuz3[1]=343653 652346 757683

 xuz1[2]=111122 111122 111122 
 xuz2[2]=222222 222222 222222 
 xuz3[2]=343653 652346 757684

也试过“grep -m 1 -e” 我应该走哪条路?

现在我最终得到一条线     grep -A4 -e“1 O1”$ out_file |切-c10-29

一些文字......是一个巨大的文字部分。

3 个答案:

答案 0 :(得分:2)

使用单个grep的一个小bash脚本就足够了

grep -E '^[0-9]+ +O[0-9]+ +.*'|
while read idx oidx cols; do
  if ((idx == 1)); then
    let ++i
    name=xuz$i
    let j=1
  fi
  echo "$name[$j]=$cols"
  let ++j
done

答案 1 :(得分:0)

你还没有真正描述过你想要的东西,但我猜是这样的。

awk '! /^[1-9][0-9]*  O[0-9] / { n++; m=0; if (NR>1) print ""; next }
    { print "xuz" ++m "[" n "]=" substr($0, 10) }' "$out_file"

如果正则表达式不匹配,我们假设我们正在查看“某些文本”部分之一,并且这会启动一条新记录。增加n并重置m。否则,在此记录中打印此项目的输出。

如果some text可能超过一行,则需要稍作更改,但我希望这应该足以让您朝着正确的方向前进。

你也可以在纯Bash中做到这一点,虽然这将是非常低效的 - 你会期望Bash while read循环至少比Awk慢一百倍,而且代码明显少于惯用而优雅。

while read -r m x result; do
  case $m::$x in
    [1-9]::O[1-9])
      printf 'xuz%d[%d]=%s\n' $m $n "$result;;
    *)
        # If n is unset, don't print an empty line
        printf '%s' "${n+$'\n'}"
        let ((n++));;
    esac
done <"$out_file"

我会积极挑战任何要求在纯Bash中执行此操作。如果是家庭作业,那么要求是不现实的,而shell脚本作者的核心技能是了解shell的限制以及像Awk这样的常用支持工具的优势。几乎可以保证Awk语言可以在任何有shell的地方使用,特别是像Bash这样的重壳。 (在有限的嵌入式环境中,像Dash这样的有限shell会更有意义。然后例如let关键字将无法使用,尽管使这个脚本可以正常移植并不困难。)

case语句接受glob模式,而不是正则表达式,因此这里的模式稍微不那么通用(我们在第一个字段中接受一个正数)。

答案 2 :(得分:0)

感谢大家参与讨论。

***这是我的家庭项目,帮助我的妻子从研究计算中提取数据///加速大约400次**

用于从中提取数据的文件,包含大约2000行, 所需的数据块看起来像这样 并且他们在文件中重复了10-20次。

 uiyououy COORDINATES

 NR  ATOM    CCCCC       X              Y              Z

   1  O1      8.00    0.000000000    0.882236820   -0.789494235
   2  O2      8.00    0.000000000   -1.218250722   -1.644061652
   3  O3      8.00    0.000000000    1.218328524    0.400260050
   4  O4      8.00    0.000000000   -0.882314622    2.033295837

 Text text text text
 tons of text 

提取4行我使用下面的表达式

grep -A4 --no-group-separator -e "1  O1" $from_file | cut -c23-64     
>xyz_temp.txt       
   # grep 4 lines at once to txt
sed -i '/^[ \t]*$/d' xyz_temp.txt                                                                                       
   #del empty lines from xyz txt

接下来是将字符串转换为数字(应该使用&#39; | bc -l&#39;用于算术)

while IFS= read line
do 
IFS=' ' read -r -a arr_line <<< "$line"                                                                             
 # break line of xyz into 3 numbers 
 s1=$(echo "${arr_line[0]}" \* 0.529177249 | bc -l)                                                        
 # some math convertion
 s2=$(echo "${arr_line[1]}" \* 0.529177249 | bc -l)
 s3=$(echo "${arr_line[2]}" \* 0.529177249 | bc -l)

 #-------to array non sorted ------------
 arr[$n]=${n}";"${from_file}";"${gd_}";"${frt[count_4s]}";"${n4}";"${s1}";"${s2}";"${s3}                                  
 echo ${arr[n]}
 #--------------------------------------------
done <"$from_file_txt"

排序数组

IFS=$'\n' sorted=($(sort -t \; -k4 -k5 -g <<<"${arr[*]}"))                      
 # -t separator ';'  -k column  -g generic   * to get new line output  
#-k4 -k5 sort by column 4 then5
#printf "%s\n" "${sorted[*]}"
unset IFS

最后一部分将数据与结果视图相结合

echo "$n"
n2=1
n42=1
count_4s2=1
i=0
echo "============================== sorted =============================="
################### loop for empty 4s lines

printf "%s" ";" ";" ";" ";" ";" "${count_4s2}" ";"
printf "%s\n"
printf "%s\n" "${sorted[i]}"
while [ $i -lt $((n-2)) ] 
 do
 i=$((i+1))
 if [ "$n42" = "4" ]                              #  1234
 then  n42=0
  count_4s2=$((count_4s2+1))
  printf "%s" ";" ";" ";" ";" ";" "${count_4s2}" ";"
  printf "%s\n"
 fi
 #--------------------------------------------
n2=$((n2+1))
n42=$((n42+1))
printf "%s\n" "${sorted[i]}"
done ############# while
#00000000000000000000000000000000000000
printf "%s\n"
echo ==END===END===END==

输出看起来像这样

============================== sorted ==============================
;;;;;1;
17;A-13_A1+.out;1.3;0.4;1;0;.221176355474853043;-.523049776514580244
18;A-13_A1+.out;1.3;0.4;2;0;-.550350051428402955;-.734584881824005358
19;A-13_A1+.out;1.3;0.4;3;0;.665269869069959489;.133910683627893251
20;A-13_A1+.out;1.3;0.4;4;0;-.336096173116409577;1.123723974181515102
;;;;;2;
13;A-13_A1+.out;1.3;0.45;1;0;.279265277182782148;-.504490787956469897
14;A-13_A1+.out;1.3;0.45;2;0;-.583907412327951988;-.759310392973448167
15;A-13_A1+.out;1.3;0.45;3;0;.662538493711206290;.146829200993661293
16;A-13_A1+.out;1.3;0.45;4;0;-.357896358566036450;1.116971979936256771
;;;;;3;
9;A-13_A1+.out;1.3;0.5;1;0;.339333719743262501;-.482029749553797105
10;A-13_A1+.out;1.3;0.5;2;0;-.612395507070451545;-.788968880150283253
11;A-13_A1+.out;1.3;0.5;3;0;.658674809217196345;.163289820251690233
12;A-13_A1+.out;1.3;0.5;4;0;-.385613021360830052;1.107708808923212876

==END===END===END==

*注意:此处可能未显示某些代码

下一步是将它粘贴到excel上;分离器。