Assign strings in a string to variables using bash

I have the following text file for which I need to compare the values ​​from each line, namely paragraphs 2-4 in relation to paragraphs 5-7. I am stuck with bash / awk / sed on this.

Sample data:

[hartford tmp]$ cat flist a1 1 2 3 xyz b1 3 2 1 zyx c1 1 2 3 1 2 3 d1 4 5 6 6 5 4 e1 abcabc f1 xyzxyz 

It works with the following script, but its just unbearably slow, probably because all echo s.

 [hartford tmp]$ cat pdelta.sh #!/bin/bash cat flist |while read rec; do f1="$(echo $rec | awk '{ print $1 }')" f2="$(echo $rec | awk '{ print $2 }')" f3="$(echo $rec | awk '{ print $3 }')" f4="$(echo $rec | awk '{ print $4 }')" f5="$(echo $rec | awk '{ print $5 }')" f6="$(echo $rec | awk '{ print $6 }')" f7="$(echo $rec | awk '{ print $7 }')" if [[ "x${f2} x${f3} x${f4}" != "x${f5} x${f6} x${f7}" ]]; then echo "$f1 DOES NOT MATCH" fi done 

On startup, the output is exactly what I am looking for, but it is too slow when working with a 50k + file.

 [hartford]$ ./pdelta.sh a1 DOES NOT MATCH b1 DOES NOT MATCH d1 DOES NOT MATCH 

What is a more efficient way to do this?

+4
source share
5 answers

You can use awk to display all matching identifiers:

 awk '{ if ($2 == $5 && $3 == $6 && $4 == $7) { print $1 } }' < flist 
+6
source

You can use read to assign variables:

 $ while read f1 f2 f3 f4 f5 f6 f7; do stuff; done <flist 
+5
source

A few fixes:

  • Do not cat separate file in the pipe; just redirect the standard input for the loop.
  • read can break each line into the corresponding variables.
  • Since you are using the bash construct [[...]] , you do not need to use the old prefix trick, possibly an empty string with one character. Just compare the corresponding values ​​directly.

So your cycle comes down to

 while read f1 f2 f3 f4 f5 f6 f7; do if [[ $f2 != $f5 || $f3 != $f6 || $f4 != $f7 ]]; then echo "$f1 DOES NOT MATCH" fi done < flist 

You can also use an array to reduce it even further.

 while read -af; do if [[ ${f[@]:1:3} != ${f[@]:4:3} ]]; then echo "${f[0]} DOES NOT MATCH" fi done < flist 

The notation ${f[@]:x:y} expands to y elements starting at index x .

+4
source

Using perl:

 perl -lane 'print $F[0] if @F[1..3] ne @F[4..6]' input_file 
+2
source

Python solution:

 import sys for line in sys.stdin: f1, f2, f3, f4, f5, f6, f7 = line.split() if not (f2, f3, f4) == (f5, f6, f7): print f1, "does not match" 

Using:

 $ python f.py < flist a1 does not match b1 does not match d1 does not match 
0
source

Source: https://habr.com/ru/post/1432451/


All Articles