Can anyone create a script for a file comparison?
The pseudo code looks like this
extract line 5 from file 1
save it in another variable,
extract line 5 from file 2,
save it in another variable,
if
variable 1 is not equal to variable 2 (while allowing for differing characters at positions 11 and 12 from the end of line)
then fail
else
pass
Unix shell? Pass the fileneames as arguments to the following script:
#!/bin/sh
a="$(head -n 5 < $1|tail -n 1)"
b="$(head -n 5 < $2|tail -n 1)"
test "$a" = "$b" && (echo The same; exit 0)
echo Different; exit 1
Related
We all know arrays in Bash are indexed from zero, and in zsh are indexed from one.
How can the script know it should use 0 or 1 if I can't ensure the running environment is bash, zsh or something else?
Expected code sample:
#!/bin/sh
detect_array_start_index(){
# ... how?
echo 1
}
ARR=(ele1 ele2)
startIndex=$(detect_array_start_index) # 0 or 1
for (( i=${startIndex}; i < ${#ARR[#]} + $startIndex; i++ )); do
echo "$i is ${ARR[$i]}"
done
I have a idea is find the index of the first value in a fixed array, I got this: Get the index of a value in a Bash array, but the accepted answer use bash variable indirection syntax ${!VAR[#]}, which is invalid in zsh.
Check the index 1 element of a two element array:
detect_array_start_index() {
local x=(1 0)
echo ${x[1]}
}
You can set the KSH_ARRAYS option in zsh to force array indexing to start at 0.
{ setopt KSH_ARRAYS || : ; } 2> /dev/null
ARR=(ele1 ele2)
for ((i=0; i < ${#ARR[#]}; i++ )); do
echo "$i is ${ARR[$i]}"
done
The command group and redirection allows the entire command to act as a no-op if executed from bash. The preceding code produces the same output in zsh and bash.
I have an array of strings to pass through a script. The script is well-behaved, and will return error code 0 if the string "passes" and non-zero if it "fails." If the string passes, it should be included in a final array to be output or written to file or etc.
The problem I'm having is that the only item ending up in my final array is the first "passing" string.
#!/bin/bash
# validator.sh
if [[ $1 -le 10 ]]; then
exit 0
else
exit 1
fi
#!/bin/bash
# main.sh
numbers=(2 4 6 8 10 12 14 16)
keep=()
for n in ${numbers[#]}; do
if ./validator.sh $n; then
keep+=("$n")
fi
done
echo $keep
Running main.sh produces:
$ ./main.sh
2
but I expect 2 4 6 8 10
Unless you meant keep to be an array of matching elements, change:
keep+=("$n")
to
keep="$keep $n"
That would work with any Bourne compatible shell and is therefore better, if you're looking for BASH specific solution, the below will also work:
keep+="${n} "
If you DO want it to be an array, then in order to output all elements, you can use:
echo ${keep[#]}
As noted by #Jetchisel and #kamilCuk in the comments.
Since you wrote you want to output all elements or save them to a file, I had assumed you don't actually need an array here but perhaps you plan to use this data in other ways later:)
I have a bash command that outputs text in the following format:
Header 1
- Point 1
- Point 2
Header 2
- Point 1
- Point 2
Header 3
-Point 1
- Point 2
...
I want to parse this text into an array, separating on the empty line so that array[0] for example contains:
Header 1
- Point 1
- Point 2
And then I want to edit some of the data in the array if it satisfies certain conditions.
I was looking at something like this Separate by blank lines in bash but I'm completely new to bash so I don't understand how to save the output from awk RS=null to an array instead of printing it out. Could someone please point me in the right direction?
You can use readarray command to populate a bash array after reading your file with gnu awk command with empty RS that lets awk split records on empty lines and using ORS as \0 (NUL) byte:
IFS= readarray -d '' arr < <(awk -v RS= -v ORS='\0' '1' file)
Check output:
echo "${arr[0]}"
Header 1
- Point 1
- Point 2
echo "${arr[1]}"
Header 2
- Point 1
- Point 2
echo "${arr[2]}"
Header 3
-Point 1
- Point 2
Online Demo
I have written the following code to read in my csv file (which has a fixed number of columns but not a fixed number of rows) into my script as an array. I need it to be a shell script.
usernames x1 x2 x3 x4
username1, 5 5 4 2
username2, 6 3 2 0
username3, 8 4 9 3
My code
#!/bin/bash
set oldIFS = $IFS
set IFS=,
read -a line < something.csv
another option I have used is
#!/bin/bash
while IFS=$'\t' reaad -r -a line
do
echo $line
done < something.csv
for both I tried some test code to see what the size of the array line would be and I seem to be getting a size of 10 with the first one but the array only outputs username. For the second one, I seem to be getting a size of 0 but the array outputs the whole csv.
Help is much appreciated!
You may consider using AWK with a regular expression in FS variable like this:
awk 'BEGIN { FS=",?[ \t]*"; } { print $1,"|",$2,"|",$3,"|",$4,"|",$5; }'
or this
awk 'BEGIN { FS=",?[ \t]*"; OFS="|"; } { $1=$1; print $0; }'
($1=$1 is required to rebuild $0 with new OFS)
I am trying to write a shell script that will search for a file name (given as an argument) and if the file was modified less than or equal to 10 minutes ago, exit 0, if it was modified more than 10 minutes ago exit 1, and if the file doesn't exist exit 2.
Here's my code:
if find $1
then
if find $1 -mmin -11
then
echo "Exit 0"
else
echo "Exit 1"
fi
else
echo "Exit 2"
fi
How do I make this search through ALL files on the system?
Also, if the file exists then check if it was modified within the past 10 minutes, if it was then exit 1. If the file doesn't exist then exit 2. I have used echo "" so that I can see which exit happens.
if [[ -n $1 ]]; then
find / -name $1 -mmtime -10 2>/dev/null
if [[ $? == 0 ]]; then
exit 0
else
exit 1
fi
else
...
What do you want to do if there are two files of that name found on the filesystem? (For the moment, I'll assume that is not an issue and only work with the first file found.) Your question contradicts itself: in the preamble you say you want to exit with 0 if it has been modified in the last 10 minutes, but later you say that a recent modification should trigger an exit of 1. The following solution returns 0 of the file has NOT been modified in the last 10 minutes. This requires the gnu extension to date that gives the %s format specifier.
#!/bin/sh
fullpath=$( find / -name ${1?No file specified} | sed 1q | grep . ) || exit 2
test $( expr $( date +%s ) - $( stat -c %Y $fullpath )) -gt 600