Why doesn't "sed" pick up on command? - bash

`When using sed and trying to pull out a specific line, it looses the p portion of "sed -n (x)p test.txt"
I'm trying to look at a line and see if its A or B.
sed -n 3p test.txt
works fine, but i'm trying to do:
sed -n $(Count) test.txt
This doesn't work
sed -n $($Count)p test.txt
Doesn't work
Count=$(cat -n test.txt | grep -o [0-9]* | tail -1)
until [ $Count = 0 ]; do
if [[ $(sed -n $(Count)p test.txt) = Him ]] || [[ $(sed -n $(Count)p model.txt) = He ]]
then
echo "This is a Boy Word"
elif [[ $(sed -n $(Count)p model.txt) = Her ]] || [[ $(sed -n $(Count)p model.txt) = She ]]
then
echo "This is an Girl Word"
fi
let Count=Count-1
sleep 1
done
I'm expecting :
This is a Boy Word
This is a Boy Word
This is a Girl Word
This is a Girl Word...
Until it has gone through all the lines,
However I'm getting (with sed -n $($Count)p test.txt)
Line 17: 3: command not found
Line 20: 3: command not found
Line 17: 2: command not found
Line 17: 2: command not found
Or (with sed -n $(Count)p test.txt
Line 17: Count: command not found
Line 20: Count: Command not found
Line 17: Count: Command not Found
Line 20: Count: command not found

You need to use the full form ${Count} to separate the variable name from an adjacent character.
sed -n ${Count}p test.txt
Or, simply quote the parameter expansion:
sed -n "$Count"p test.txt

Related

how to move string from position to position in bash (sed, awk)

Please help me:)
How to move string from 4-line to under 1-line in bash (awk, sed)?
Example, i have a file:
line1
line2
line3
moveline4
result use SED, AWK and other utils:
line1
moveline4
line2
line3
Another approach with sed:
sed '2{N;h;d};4G;' file
Explanations:
2N: merges second and third line
h: stores both lines into the hold space
d: deletes both lines
4G: adds the pattern space content after fourth line
input file:
line1
line2
line3
moveline4
line5
line6
sed solution:
sed -n -e '1p' -e '4p' lines.txt; sed -n -e '2,3p' -e '5,$p' lines.txt
output:
line1
moveline4
line2
line3
line5
line6
You can redirect your ouput to a specific file (> and >>)
sed -n -e '1p' -e '4p' lines.txt > new_file.txt; sed -n -e '2,3p' -e '5,$p' lines.txt >> new_file.txt
explanation:
-n to avoid default printing of lines
-e to pass several commands to sed
1p to print the first line
4p to print the 4th line
2,3p to print the 2nd and 3rd line
5,$p to print the 5th line to the last line
awk solution:
awk 'NR==1||NR==4' lines.txt; awk 'NR>=2 && NR!=4' lines.txt
You can redirect your ouput to a specific file (> and >>)
awk 'NR==1||NR==4' lines.txt > new_file.txt; awk 'NR>=2 && NR!=4' lines.txt >> new_file.txt
explanation:
NR==1||NR==4 will make awk do its default action for number record 1 or 4 which is printing (lines 1 and 4)
NR>=2 && NR!=4 for lines >=2 and !=4 you print them
head/tail solution:
head -1 lines.txt; head -4 lines.txt| tail -1; head -3 lines.txt | tail -2; tail -n +5 lines.txt
for information about the behavior of head and tail please do man head and man tail
perl solution:
perl -ne 'print if 1..1' lines.txt; perl -ne 'print if 4..4' lines.txt; perl -ne 'print if 2..3' lines.txt; perl -ne 'print if 5..6' lines.txt
full bash solution:
#!/usr/bin/env bash
#print the 1st line
while IFS='' read -r line || [[ -n "$line" ]]; do
echo "$line"
break
done <"$1"
#print the 4th line
x=1
while IFS='' read -r line || [[ -n "$line" ]]; do
if [ $x -eq 4 ]; then
echo "$line"
break
fi
x=$((x+1))
done <"$1"
#print all lines except the 1st and the 4th
x=1
while IFS='' read -r line || [[ -n "$line" ]]; do
if [ $x -ne 1 -a $x -ne 4 ]; then
echo "$line"
fi
x=$((x+1))
done <"$1"
you can call the script ./myscript.sh lines.txt and redirect the output if necessary: ./myscript.sh lines.txt > new_file.txt

bash / Variable value is empty after the loop

I'm new to bash and try a simple loop but the value of my variable is being lost after it and I can not understand why - I have looked at few similar issues but they are all related to subshell execution of a while loop . I'm not doing but still facing issues - can someone explain me where is my mistake ?
#!/bin/bash
check_ss ()
{
command_list | awk '{print $1 $9}' > ss.out
for i in {1..8}
do grep -Pa "\x3$i" ss.out > ss$i.out
if grep -w "NotStarted" ss$i.out
then
ss$i=0
else
ss$i=1
fi
done
}
check_ss
echo $ss1
echo $ss2
echo $ss3
echo $ss4
I'm getting this on execution :
[root#lubo ~]# ./ss.sh
./ss.sh: line 21: ss1=1: command not found
./ss.sh: line 21: ss2=1: command not found
./ss.sh: line 21: ss3=1: command not found
./ss.sh: line 21: ss4=1: command not found
./ss.sh: line 21: ss5=1: command not found
./ss.sh: line 21: ss6=1: command not found
./ss.sh: line 21: ss7=1: command not found
./ss.sh: line 21: ss8=1: command not found
Thanks in advance
You need to use declare to dynamically construct a variable name.
declare "ss$i=0"
An array would be a better alternative to dynamic variable names.
check_ss() {
ss=()
command_list | awk '{print $1 $9}' > ss.out
for i in {1..8}; do
grep -Pa "\x3$i" ss.out > ss$i.out
if grep -w "NotStarted" ss$i.out; then
ss[$i]=0
else
ss[$i]=1
fi
done
}
check_ss
echo ${ss[1]}
echo ${ss[2]}
echo ${ss[3]}
echo ${ss[4]}
You could also get rid of the temporary files.
check_ss() {
ss=()
command_list | awk '{print $1 $9}' > ss.out
for i in {1..8}; do
if grep -Pa "\x3$i" ss.out | grep -w "NotStarted"; then
ss[$i]=0
else
ss[$i]=1
fi
done
}
I don't know what your input looks like exactly, but you might even be able to simplify it further to something like:
check_ss() {
ss=()
while read i; do
ss[$i]=1
done < <(command_list | awk '$9=="NotStarted" {print $1}')
}
or if you just want a list of the NotStarted numbers,
ss=(command_list | awk '$9=="NotStarted" {print $1}')
echo "${ss[#]}"

Correctly count number of lines a bash variable

I need to count the number of lines of a given variable. For example I need to find how many lines VAR has, where VAR=$(git log -n 10 --format="%s").
I tried with echo "$VAR" | wc -l), which indeed works, but if VAR is empty, is prints 1, which is wrong. Is there a workaround for this? Something better than using an if clause to check whether the variable is empty...(maybe add a line and subtract 1 from the returned value?).
The wc counts the number of newline chars. You can use grep -c '^' for counting lines.
You can see the difference with:
#!/bin/bash
count_it() {
echo "Variablie contains $2: ==>$1<=="
echo -n 'grep:'; echo -n "$1" | grep -c '^'
echo -n 'wc :'; echo -n "$1" | wc -l
echo
}
VAR=''
count_it "$VAR" "empty variable"
VAR='one line'
count_it "$VAR" "one line without \n at the end"
VAR='line1
'
count_it "$VAR" "one line with \n at the end"
VAR='line1
line2'
count_it "$VAR" "two lines without \n at the end"
VAR='line1
line2
'
count_it "$VAR" "two lines with \n at the end"
what produces:
Variablie contains empty variable: ==><==
grep:0
wc : 0
Variablie contains one line without \n at the end: ==>one line<==
grep:1
wc : 0
Variablie contains one line with \n at the end: ==>line1
<==
grep:1
wc : 1
Variablie contains two lines without \n at the end: ==>line1
line2<==
grep:2
wc : 1
Variablie contains two lines with \n at the end: ==>line1
line2
<==
grep:2
wc : 2
You can always write it conditionally:
[ -n "$VAR" ] && echo "$VAR" | wc -l || echo 0
This will check whether $VAR has contents and act accordingly.
For a pure bash solution: instead of putting the output of the git command into a variable (which, arguably, is ugly), put it in an array, one line per field:
mapfile -t ary < <(git log -n 10 --format="%s")
Then you only need to count the number of fields in the array ary:
echo "${#ary[#]}"
This design will also make your life simpler if, e.g., you need to retrieve the 5th commit message:
echo "${ary[4]}"
try:
echo "$VAR" | grep ^ | wc -l

How to search a line containing word in file and from that line to end of file should be echo the date using shell script

cat "file.log"| grep -q '2013-11-10'
while read line
do
echo file_content_time=`echo $line | sed -e 's/\([0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0- 9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9]\).*/\1/'`
if [ $? -eq 0 ]
then
echo comparison_start_date=`date -d "$file_content_time" +%Y%m%d`
fi
done < 'file.log'
/* Here I am trying find out the line containing '2013-11-10' and from that line onwards date has to display .*/
To output everything from a line containing a pattern up to the end-of-file all you need is
awk '/2013-11-10/,/pattern-not-in-file/' file.log
awk '/pattern/{p=1}p' your_file
initial_time=$(grep -o -m1 "2013-11-10 [0-9][0-9]:[0-9][0-9]:[0-9][0-9]" file.log)

Cat command Unexpected delimited by end-of-file

I have the script
#!/bin/bash
set i=0;
while read line
do
echo "$line";
$i < cat "my.log" | grep -w "$line" | wc -l;
echo "$i";
if [ "$i" == 0 ]; then
cat $line << "notfound.txt"
fi
i=0;
done < "test.txt"
which is giving the error
./test.sh: line 13: warning: here-document at line 10 delimited by end-of-file (wanted `notfound.txt')
./test.sh: line 14: syntax error: unexpected end of file
My goal is to test the value of the variable i. If it is 0 then I would like to redirect the value stored in the variable $line to a file "notfound.txt"
Instead of
cat $line << "notfound.txt"
say:
echo $line > "notfound.txt"
You don't cat variables, you echo those instead. command > file would redirect the output of the command to the file, overwriting it. If you want to append the file, use >> instead.
You can learn more about redirection here.

Resources