Get the data from specific entry - linux

I have below one line entry stored in variable. I want to grep only worker and batch count from below entry and store in another two variables ts=13/12
/202213:07:34:|name=xyz|worker=5|batch=100|conf_file=/path/to/file|data_dir=/path/to/folder|logs_dir=/data/logs/
form above example worker=5 and batch=100
so I want to store 5 in a i.e a=5 and b=100
Note: The length of the entry is not fixed
echo $ENTRY | grep "worker" | cut -d "=" -f4
using above I am getting below output
5|batch

$ IFS='|' read _ _ w b _ <<< '/202213:07:34:|name=xyz|worker=5|batch=100|conf_file=/path/to/file|data_dir=/path/to/folder|logs_dir=/data/logs/'
$ echo "${w#*=}"
5
$ echo "${b#*=}"
100

Using bash's =~ operator:
[[ $entry =~ '|worker='([^|]*) ]] && worker=${BASH_REMATCH[1]}
[[ $entry =~ '|batch='([^|]*) ]] && batch=${BASH_REMATCH[1]}
echo "$worker/$batch"

Related

Unix - Replace column value inside while loop

I have comma separated (sometimes tab) text file as below:
parameters.txt:
STD,ORDER,ORDER_START.xml,/DML/SOL,Y
STD,INSTALL_BASE,INSTALL_START.xml,/DML/IB,Y
with below code I try to loop through the file and do something
while read line; do
if [[ $1 = "$(echo "$line" | cut -f 1)" ]] && [[ "$(echo "$line" | cut -f 5)" = "Y" ]] ; then
//do something...
if [[ $? -eq 0 ]] ; then
// code to replace the final flag
fi
fi
done < <text_file_path>
I wanted to update the last column of the file to N if the above operation is successful, however below approaches are not working for me:
sed 's/$f5/N/'
'$5=="Y",$5=N;{print}'
$(echo "$line" | awk '$5=N')
Update: Few considerations which need to be considered to give more clarity which i missed at first, apologies!
The parameters file may contain lines with last field flag as "N" as well.
Final flag needs to be update only if "//do something" code has successfully executed.
After looping through all lines i.e, after exiting "while loop" flags for all rows to be set to "Y"
perhaps invert the operations do processing in awk.
$ awk -v f1="$1" 'BEGIN {FS=OFS=","}
f1==$1 && $5=="Y" { // do something
$5="N"}1' file
not sure what "do something" operation is, if you need to call another command/script it's possible as well.
with bash:
(
IFS=,
while read -ra fields; do
if [[ ${fields[0]} == "$1" ]] && [[ ${fields[4]} == "Y" ]]; then
# do something
fields[4]="N"
fi
echo "${fields[*]}"
done < file | sponge file
)
I run that in a subshell so the effects of altering IFS are localized.
This uses sponge to write back to the same file. You need the moreutils package to use it, otherwise use
done < file > tmp && mv tmp file
Perhaps a bit simpler, less bash-specific
while IFS= read -r line; do
case $line in
"$1",*,Y)
# do something
line="${line%Y}N"
;;
esac
echo "$line"
done < file
To replace ,N at the end of the line($) with ,Y:
sed 's/,N$/,Y/' file

How to change/overwrite certain characters in a string?

I've written up a 'hang-man' type game in bash. Which is currently working, but I just cannot get my head around on how to overwrite certain characters in the string.
So currently I get a letter (eg 'l') from the user and it checks it against a string 'hello' and prints out as ' _ _ l l _ ' ({is $prev in the code) I would like when the user enters 'e', the $prev to get updated to ' _ e l l _ ' and so on and so forth for 'h' and 'o'.
Q: How would I be able to change a certain character in a string?
If you want to manipulate individual characters in a variable, then it is easier to hold all characters in an array. That way you can change the characters based on array index. Below shows a simple way to convert to/from an array while manipulating the characters. Note: there is no need to convert back to a variable, you can simply maintain the word being guessed at in an array:
#!/bin/bash
declare -a array
prev="__||_" ## previous state of guessing
printf "%s\n" "$prev"
for ((i=0; i<${#prev}; i++)); do ## convert to array
array+=( ${prev:i:1} )
done
array[1]="e" ## update letter
## convert back to string
printf -v prev $(echo ${array[#]} | tr -d ' ')
printf "%s\n" "$prev"
Output
$ bash ~/scr/tmp/stack/strtoarray.sh
__||_
_e||_
An implementation of hangman using arrays for the word and the answer. It picks a random word from the file pointed to by ${words}.
#!/usr/bin/env bash
words='/usr/share/dict/words'
die() { >&2 echo $#; exit 1; }
join() { local IFS="$1"; shift; echo "$*"; }
new_word() {
unset word
local length=$(wc -l < ${words})
local count=$((${RANDOM} % ${length}))
head -${count} ${words} | tail -1 | tr '[:upper:]' '[:lower:]'
}
draw_hangman() {
# draw hangman here
((++guesses))
}
[[ -f ${words} ]] || die "Missing words file: ${words}"
declare -i guesses=0
declare -a word=( $(new_word | grep -o .) )
declare -a answer=( $(printf '_ %.0s' $(seq 1 ${#word[#]})) )
while :; do
echo -e "\nPress - to quit.\n"
echo -e "${answer[#]}\n"
read -s -n 1 -p "$((${#word[#]} - ${guesses})) more guesses: " guess
echo
[[ ${guess} == '-' ]] && echo && break # quit
[[ ${guesses} -eq $((${#word[#]} - 1)) ]] && echo -e "\nYOU LOSE!\n" && \
echo "The word was $(join '' ${word[#]})" && break
[[ ${word[#]} != *${guess}* ]] && draw_hangman && continue
for i in ${!word[#]}; do
[[ ${word[${i}]} == ${guess} ]] && answer[${i}]=${guess}
done
[[ ${answer[#]} == ${word[#]} ]] && echo -e "\nYOU WIN!\n" && break
done

greping a character from file UNIX.linux bash. Can't pass an argument(file name) through command line

I am having trouble with my newbie linux script which needs to count brackets and tell if they are matched.
#!/bin/bash
file="$1"
x="()(((a)(()))"
left=$(grep -o "(" <<<"$x" | wc -l)
rght=$(grep -o ")" <<<"$x" | wc -l)
echo "left = $left right = $rght"
if [ $left -gt $rght ]
then echo "not enough brackets"
elif [ $left -eq $rght ]
then echo "all brackets are fine"
else echo "too many"
fi
the problem here is i can't pass an argument through command line so that grep would work and count the brackets from the file. In the $x place I tried writing $file but it does not work
I am executing the script by writting: ./script.h test1.txt the file test1.txt is on the same folder as script.h
Any help in explaining how the parameter passing works would be great. Or maybe other way to do this script?
The construct <<< is used to transmit "the contents of a variable", It is not applicable to "contents of files". If you execute this snippet, you could see what I mean:
#!/bin/bash
file="()(((a)((a simple test)))"
echo "$( cat <<<"$file" )"
which is also equivalent to just echo "$file". That is, what is being sent to the console are the contents of the variable "file".
To get the "contents of a file" which name is inside a var called "file", then do:
#!/bin/bash
file="test1.txt"
echo "$( cat <"$file" )"
which is exactly equivalent to echo "$( <"$file" )", cat <"$file" or even <"$file" cat
You can use: grep -o "(" <"$file" or <"$file" grep -o "("
But grep could accept a file as a parameter, so this: grep -o "(" "$file" also works.
However, I believe that tr would be a better command, as this: <"$file" tr -cd "(".
It transforms the whole file into a sequence of "(" only, which will need a lot less to be transmitted (passed) to the wc command. Your script would become, then:
#!/bin/bash -
file="$1"
[[ $file ]] || exit 1 # make sure the var "file" is not empty.
[[ -r $file ]] || exit 2 # test if the file "file" exists.
left=$(<"$file" tr -cd "("| wc -c)
rght=$(<"$file" tr -cd ")"| wc -c)
echo "left = $left right = $rght"
# as $left and $rght are strictly numeric values, this integer tests work:
(( $left > $rght )) && echo "not enough right brackets"
(( $left == $rght )) && echo "all brackets are fine"
(( $left < $rght )) && echo "too many right brackets"
# added as per an additional request of the OP.
if [[ $(<"$file" tr -cd "()"|head -c1) = ")" ]]; then
echo "the first character is (incorrectly) a right bracket"
fi

Check if a variable exists in a list in Bash

I am trying to write a script in bash that check the validity of a user input.
I want to match the input (say variable x) to a list of valid values.
what I have come up with at the moment is:
for item in $list
do
if [ "$x" == "$item" ]; then
echo "In the list"
exit
fi
done
My question is if there is a simpler way to do this,
something like a list.contains(x) for most programming languages.
Say list is:
list="11 22 33"
my code will echo the message only for those values since list is treated as an array and not a string,
all the string manipulations will validate 1 while I would want it to fail.
[[ $list =~ (^|[[:space:]])$x($|[[:space:]]) ]] && echo 'yes' || echo 'no'
or create a function:
contains() {
[[ $1 =~ (^|[[:space:]])$2($|[[:space:]]) ]] && exit(0) || exit(1)
}
to use it:
contains aList anItem
echo $? # 0: match, 1: failed
how about
echo $list | grep -w -q $x
you could either check the output or $? of above line to make the decision.
grep -w checks on whole word patterns. Adding -q prevents echoing the list.
Matvey is right, but you should quote $x and consider any kind of "spaces" (e.g. new line) with
[[ $list =~ (^|[[:space:]])"$x"($|[[:space:]]) ]] && echo 'yes' || echo 'no'
so, i.e.
# list_include_item "10 11 12" "2"
function list_include_item {
local list="$1"
local item="$2"
if [[ $list =~ (^|[[:space:]])"$item"($|[[:space:]]) ]] ; then
# yes, list include item
result=0
else
result=1
fi
return $result
}
end then
`list_include_item "10 11 12" "12"` && echo "yes" || echo "no"
or
if `list_include_item "10 11 12" "1"` ; then
echo "yes"
else
echo "no"
fi
Note that you must use "" in case of variables:
`list_include_item "$my_list" "$my_item"` && echo "yes" || echo "no"
IMHO easiest solution is to prepend and append the original string with a space and check against a regex with [[ ]]
haystack='foo bar'
needle='bar'
if [[ " $haystack " =~ .*\ $needle\ .* ]]; then
...
fi
this will not be false positive on values with values containing the needle as a substring, e.g. with a haystack foo barbaz.
(The concept is shamelessly stolen form JQuery's hasClass()-Method)
You can use (* wildcards) outside a case statement, too, if you use double brackets:
string='My string';
if [[ $string == *My* ]]
then
echo "It's there!";
fi
If it isn't too long; you can just string them between equality along a logical OR comparison like so.
if [ $ITEM == "item1" -o $ITEM == "item2" -o $ITEM == "item3" ]; then
echo In the list
fi
I had this exact problem and while the above is ugly it is more obvious what is going on than the other generalized solutions.
If your list of values is to be hard-coded in the script, it's fairly simple to test using case. Here's a short example, which you can adapt to your requirements:
for item in $list
do
case "$x" in
item1|item2)
echo "In the list"
;;
not_an_item)
echo "Error" >&2
exit 1
;;
esac
done
If the list is an array variable at runtime, one of the other answers is probably a better fit.
There's a cleaner way to check if string is in the list:
if [[ $my_str = #(str1|str2|str3) ]]; then
echo "string found"
fi
Consider exploiting the keys of associative arrays. I would presume this outperforms both regex/pattern matching and looping, although I haven't profiled it.
declare -A list=( [one]=1 [two]=two [three]='any non-empty value' )
for value in one two three four
do
echo -n "$value is "
# a missing key expands to the null string,
# and we've set each interesting key to a non-empty value
[[ -z "${list[$value]}" ]] && echo -n '*not* '
echo "a member of ( ${!list[*]} )"
done
Output:
one is a member of ( one two three )
two is a member of ( one two three )
three is a member of ( one two three )
four is *not* a member of ( one two three )
If the list is fixed in the script, I like the following the best:
validate() {
grep -F -q -x "$1" <<EOF
item 1
item 2
item 3
EOF
}
Then use validate "$x" to test if $x is allowed.
If you want a one-liner, and don't care about whitespace in item names, you can use this (notice -w instead of -x):
validate() { echo "11 22 33" | grep -F -q -w "$1"; }
Notes:
This is POSIX sh compliant.
validate does not accept substrings (remove the -x option to grep if you want that).
validate interprets its argument as a fixed string, not a regular
expression (remove the -F option to grep if you want that).
Sample code to exercise the function:
for x in "item 1" "item2" "item 3" "3" "*"; do
echo -n "'$x' is "
validate "$x" && echo "valid" || echo "invalid"
done
I find it's easier to use the form echo $LIST | xargs -n1 echo | grep $VALUE as illustrated below:
LIST="ITEM1 ITEM2"
VALUE="ITEM1"
if [ -n "`echo $LIST | xargs -n1 echo | grep -e \"^$VALUE`$\" ]; then
...
fi
This works for a space-separated list, but you could adapt it to any other delimiter (like :) by doing the following:
LIST="ITEM1:ITEM2"
VALUE="ITEM1"
if [ -n "`echo $LIST | sed 's|:|\\n|g' | grep -e \"^$VALUE`$\"`" ]; then
...
fi
Note that the " are required for the test to work.
Thought I'd add my solution to the list.
# Checks if element "$1" is in array "$2"
# #NOTE:
# Be sure that array is passed in the form:
# "${ARR[#]}"
elementIn () {
# shopt -s nocasematch # Can be useful to disable case-matching
local e
for e in "${#:2}"; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
# Usage:
list=(11 22 33)
item=22
if elementIn "$item" "${list[#]}"; then
echo TRUE;
else
echo FALSE
fi
# TRUE
item=44
elementIn $item "${list[#]}" && echo TRUE || echo FALSE
# FALSE
The shell built-in compgen can help here. It can take a list with the -W flag and return any of the potential matches it finds.
# My list can contain spaces so I want to set the internal
# file separator to newline to preserve the original strings.
IFS=$'\n'
# Create a list of acceptable strings.
accept=( 'foo' 'bar' 'foo bar' )
# The string we will check
word='foo'
# compgen will return a list of possible matches of the
# variable 'word' with the best match being first.
compgen -W "${accept[*]}" "$word"
# Returns:
# foo
# foo bar
We can write a function to test if a string equals the best match of acceptable strings. This allows you to return a 0 or 1 for a pass or fail respectively.
function validate {
local IFS=$'\n'
local accept=( 'foo' 'bar' 'foo bar' )
if [ "$1" == "$(compgen -W "${accept[*]}" "$1" | head -1)" ] ; then
return 0
else
return 1
fi
}
Now you can write very clean tests to validate if a string is acceptable.
validate "blah" || echo unacceptable
if validate "foo" ; then
echo acceptable
else
echo unacceptable
fi
Prior answers don't use tr which I found to be useful with grep. Assuming that the items in the list are space delimited, to check for an exact match:
echo $mylist | tr ' ' '\n' | grep -F -x -q "$myitem"
This will return exit code 0 if the item is in the list, or exit code 1 if it isn't.
It's best to use it as a function:
_contains () { # Check if space-separated list $1 contains line $2
echo "$1" | tr ' ' '\n' | grep -F -x -q "$2"
}
mylist="aa bb cc"
# Positive check
if _contains "${mylist}" "${myitem}"; then
echo "in list"
fi
# Negative check
if ! _contains "${mylist}" "${myitem}"; then
echo "not in list"
fi
Late to the show? Following very easy variant was not clearly mentioned yet. I use case for checking simple lists, which is a general Bourne Shell idiom not relying on anything external nor extended:
haystack='a b c'
needle='b'
case " $haystack " in (*" $needle "*) :;; (*) false;; esac
Please note the use of the separator (here: SPC) to correcyly delimit the pattern: At the beginning and end of " $haystack " and likewise in the test of " $needle ".
This statement returns true ($?=0) in case $needle is in $haystack, false otherwise.
Also you can test for more than one $needle very easily. When there are several similar cases like
if (haystack.contains(needle1)) { run1() } elif (haystack.contains(needle2)) { run2() } else { run3() }
you can wrap this into the case, too:
case " $haystack " in (*" $needle1 "*) run1;; (*" $needle2 "*) run2;; (*) run3;; esac
and so on
This also works for all lists with values which do not include the separator itself, like comma:
haystack=' a , b , c '
needle=' b '
case ",$haystack," in (*",$needle,"*) :;; (*) false;; esac
Note that if values can contain anything including the separator sequence (except NUL, as shells do not suport NUL in variables as you cannot pass arguments containing NUL to commands) then you need to use arrays. Arrays are ksh/bashisms and not supported by "ordinary" POSIX/Bourne shells. (You can work around this limitation using $# in POSIX-Shells, but this is something completely different than what was aked here.)
Can the (*) false part be left away?
No, as this is the critical return value. By default case returns true.
Yes if you do not need the return value and put your processing at the location of the :
Why the :;;
We could also write true;;, but I am used to use : instead of true because it is shorter and faster to type
Also I consider not writing anything bad practice, as it is not obvious to everybody that the default return value of case is true.
Also "leaving out" the command usually indicates "something was forgotten here". So putting a redundant ":" there clearly indicates "it is intended to do nothing else than return true here".
In bash you can also use ksh/bashisms like ;& (fallthroug) or ;;& (test other patterns) to express if (haystack.contains(needle1)) { run1(); }; if (haystack.contains(needle2)) { run2(); }
Hence usually case is much more maintainable than other regex constructs. Also it does not use regex, it only use shell patterns, which might even be faster.
Reusable function:
: Needle "list" Seperator_opt
NeedleListSep()
{
if [ 3 -gt $# ];
then NeedleListSep "$1" "$2" " ";
else case "$3$2$3" in (*"$3$1$3"*) return 0;; esac; return 1;
fi;
}
In bash you can simplify this to
: Needle "list" Seperator_opt
NeedleListSep()
{
local s="${3-" "}";
case "$s$2$s" in (*"$s$1$s"*) return 0;; esac; return 1;
}
Use like this
Test() {
NeedleListSep "$1" "a b c" && echo found $1 || echo no $1;
NeedleListSep "$1" "a,b,c" ',' && echo found $1 || echo no $1;
NeedleListSep "$1" "a # b # c" ' # ' && echo found $1 || echo no $1;
NeedleListSep "$1" "abc" '' && echo found $1 || echo no $1;
}
Test a
Test z
As shown above, this also works for degerated cases where the separator is the empty string (so each character of the list is a needle). Example:
Test
returns
no
no
no
found
As the empty string is cleary part of abc in case your separator is the empty string, right?
Note that this function is Public Domain as there is absolutely nothing to it which can be genuinely copyrighted.
An alternative solution inspired by the accepted response, but that uses an inverted logic:
MODE="${1}"
echo "<${MODE}>"
[[ "${MODE}" =~ ^(preview|live|both)$ ]] && echo "OK" || echo "Uh?"
Here, the input ($MODE) must be one of the options in the regular expression ('preview', 'live', or 'both'), contrary to matching the whole options list to the user input. Of course, you do not expect the regular expression to change.
Examples
$ in_list super test me out
NO
$ in_list "super dude" test me out
NO
$ in_list "super dude" test me "super dude"
YES
# How to use in another script
if [ $(in_list $1 OPTION1 OPTION2) == "NO" ]
then
echo "UNKNOWN type for param 1: Should be OPTION1 or OPTION2"
exit;
fi
in_list
function show_help()
{
IT=$(CAT <<EOF
usage: SEARCH_FOR {ITEM1} {ITEM2} {ITEM3} ...
e.g.
a b c d -> NO
a b a d -> YES
"test me" how "test me" -> YES
)
echo "$IT"
exit
}
if [ "$1" == "help" ]
then
show_help
fi
if [ "$#" -eq 0 ]; then
show_help
fi
SEARCH_FOR=$1
shift;
for ITEM in "$#"
do
if [ "$SEARCH_FOR" == "$ITEM" ]
then
echo "YES"
exit;
fi
done
echo "NO"
Assuming TARGET variable can be only 'binomial' or 'regression', then following would do:
# Check for modeling types known to this script
if [ $( echo "${TARGET}" | egrep -c "^(binomial|regression)$" ) -eq 0 ]; then
echo "This scoring program can only handle 'binomial' and 'regression' methods now." >&2
usage
fi
You could add more strings into the list by separating them with a | (pipe) character.
Advantage of using egrep, is that you could easily add case insensitivity (-i), or check more complex scenarios with a regular expression.
This is almost your original proposal but almost a 1-liner. Not that complicated as other valid answers, and not so depending on bash versions (can work with old bashes).
OK=0 ; MP_FLAVOURS="vanilla lemon hazelnut straciatella"
for FLAV in $MP_FLAVOURS ; do [ $FLAV == $FLAVOR ] && { OK=1 ; break; } ; done
[ $OK -eq 0 ] && { echo "$FLAVOR not a valid value ($MP_FLAVOURS)" ; exit 1 ; }
I guess my proposal can still be improved, both in length and style.
Simple oneliner...
if [[ " 11 22 33 " == *" ${x} "* ]]; then echo "${x} is in the list"; fi;
Add before fi: else echo "${x} is NOT in the list";
The script below implements contains function for a list.
function contains {
local target=$1
shift
printf '%s\n' "$#" | grep -x -q "$target"
out=$?
(( out = 1 - out ))
return $out
}
If you convert a string based on white space into a list and use it, it seems to be solved as follows.
list="11 22 33"
IFS=" " read -ra parsed_list <<< "$list"
# parsed_list would be ("11" "22" "33")
contains "11" "${parsed_list[#]}"
echo $? # 1
contains "22" "${parsed_list[#]}"
echo $? # 1
contains "1" "${parsed_list[#]}"
echo $? # 0
contains "11 22" "${parsed_list[#]}"
echo $? # 0

Bash Comparing strings in a directory

Hi I am trying to compare two strings in a directory. the format is as follows.
{sametext}difference{sametext}.
Note: {sametext} is not static for each file
for example
myfile_1_exercise.txt compared to myfile_2_exercise.txt
Can you tell me how I would match the above strings in an if statement.
Basically I need to know how I would ignore the number in the two strings so that these would be same.
Some example code is shown below:
My example code looks like this:
for g in `ls -d */`;
do
if [ -d $g ]; then
cd $g # down 1 directories
for h in `ls *root`;
do
printf "${Process[${count}]} = ${basedir}/${f}${g}${h}\n"
h1=${h}
if [ "${h1}" = "${h2}" ]; then # NEED to MATCH SOME HOW??????????
echo we have a match
fi
h2=${h1}
let count+=1
done
cd ../
#printf "\n\n\n\n"
fi
done
What should be the test to determine this instead of "${h1}" = "${h2}"?
Cheers,
Mike
"myfile_1_exercise.txt" == "myfile_2_exercise.txt"
You mean the above test should return true (ignoring the numbers) right?
This is what I would have done:
h1="myfile_1_exercise.txt"
h2="myfile_2_exercise.txt"
if [ $( echo ${h1} | sed 's/[0-9]*//g' ) == $( echo ${h2} | sed 's/[0-9]*//g' ) ] ; then
# do something here.
fi
sed comes in handy here.
This basically goes through every file in the directory, extracts the two strings from the filename, and keeps a list of all the unique combinations thereof.
Then, it walks through this list, and uses bash's wildcard expansion to allow you to loop over each collection.
EDIT: Got rid of an ugly hack.
i=0
for f in *_*_*.txt
do
a=`echo "$f" | sed 's/\(.*\)_.*_\(.*\).txt/\1/g'`
b=`echo "$f" | sed 's/\(.*\)_.*_\(.*\).txt/\2/g'`
tmp=${all[#]}
expr match "$tmp" ".*$a:$b.*" >/dev/null
if [ "$?" == "1" ]
then
all[i]="$a:$b"
let i+=1
fi
done
for f in ${all[#]}
do
a=`echo "$f" | sed 's/\(.*\):\(.*\)/\1/g'`
b=`echo "$f" | sed 's/\(.*\):\(.*\)/\2/g'`
echo $a - $b
for f2 in $a_*_$b.txt
do
echo " $f2"
# ...
done
done
Of course, this assumes that all the files you care about follow the *_*_*.txt pattern.
Disclaimer:
Mileage can vary and you may have to adjust and debug the script for corner cases.
You may be better off using Perl for your task.
There could be better solutions even in Bash. This one is not very efficient but it seems to work.
Said that, here is a script that compares two strings according to your requirements. I am sure you can figure how to use it in your directory listing script (for which you may want to consider find by the way)
This script takes two strings and prints match! if they match
$ bash compare.sh myfile_1_exercise.txt myfile_2_exercise.txt
match!
$ bash compare.sh myfile_1_exercise.txt otherfile_2_exercise.txt
$
The script:
#!/bin/bash
fname1=$1
fname2=$2
findStartMatch() {
match=""
rest1=$1 ;
rest2=$2 ;
char1=""
char2=""
while [[ "$rest1" != "" && "$rest2" != "" && "$char1" == "$char2" ]] ; do
char1=$(echo $rest1 | sed 's/\(.\).*/\1/');
rest1=$(echo $rest1 | sed 's/.\(.*\)/\1/') ;
char2=$(echo $rest2 | sed 's/\(.\).*/\1/');
rest2=$(echo $rest2 | sed 's/.\(.*\)/\1/') ;
if [[ "$char1" == "$char2" ]] ; then
match="${match}${char1}"
fi
done
}
findEndMatch() {
match=""
rest1=$1 ;
rest2=$2 ;
char1=""
char2=""
while [[ "$rest1" != "" && "$rest2" != "" && "$char1" == "$char2" ]] ; do
char1=$(echo $rest1 | sed 's/.*\(.\)/\1/');
rest1=$(echo $rest1 | sed 's/\(.*\)./\1/') ;
char2=$(echo $rest2 | sed 's/.*\(.\)/\1/');
rest2=$(echo $rest2 | sed 's/\(.*\)./\1/') ;
if [[ "$char1" == "$char2" ]] ; then
match="${char1}${match}"
fi
done
}
findStartMatch $fname1 $fname2
startMatch=$match
findEndMatch $fname1 $fname2
endMatch=$match
if [[ "$startMatch" != "" && "$endMatch" != "" ]] ; then
echo "match!"
fi
If you are actually comparing two files like you mentiond ... probably you can use diff command like
diff myfile_1_exercise.txt myfile_2_exercise.txt

Resources