i'm trying to get a file name, and a character index, and to print me the characters with that index from each line (and do it for each character index the user enters if such character exists).
This is my code:
#!/bin/bash
read file_name
while read x
do
if [ -f $file_name ]
then
while read string
do
counter=0
while read -n char
do
if [ $counter -eq $x ]
then
echo $char
fi
counter=$[$counter+1]
done < $(echo -n "$string")
done < $file_name
fi
done
But, it says an error:
line 20: abcdefgh: No such file or directory
line 20 is the last done, so it doesn't help me figure out where is the error.
So what's wrong in my code and how do I fix it?
Thanks a lot.
I think "cut" might fit the bill:
read file_name
if [ -f $file_name ]
then
while read -n char
do
cut -c $char $file_name
done
fi
This line seems to be problematic:
done < $(echo -n "$string")
Replace that with:
done < <(echo -n "$string")
replace
counter=0
while read -n char
do
if [ $counter -eq $x ]
then
echo $char
fi
counter=$[$counter+1]
done < $(echo -n "$string")
with
if [ $x -lt ${#string} ]
then
echo ${line:$x:1}
fi
It does the same, but allows to avoid such errors.
Another approach is using cut
cut -b $(($x+1)) $file_name | grep -v "^$"
It can replace two inner loops
Related
Can anyone help me with the below. I do not understand what is wrong, Not getting any output. My requirement is to read a file and check if it's not empty and to print the content line by line.
#!/bin/ksh
echo " enter file name "
read $file
if [ -f "$file" ] && [ -s "$file" ]
then
echo " file does not exist, or is empty "
else
while IFS='' read -r line || [[ -n "$file" ]];do
echo "$line"
done
fi
read $file should be read file
Your comparison logic is backwards.
The comparison if [ -f "$file" ] && [ -s "$file" ] is 'if the file is a regular file and not empty go into error case'. You want 'if the file is not regular or the file is empty go into error case' if [ -f "$file" ] -eq 0 || [ -s "$file" ] -eq 0.
Per ksh file read should be
while IFS='' read -r line
do
echo "$line"
done < "$file"
Further Reading On ksh redirection
I want to cut CSV file by column names.
Sample file:
"column A","column B","column C","column D","column E",
aaa,bbb,ccc,ddd,eee,
111,222,333,444,555
column_A:
$ cat column_A
aaa
111
column_B:
$ cat column_B
bbb
222
when I using awk but it's not success. Some time when we meet \n in "".
Like this:
aaa,ssss,"zzz
xxx"
but this should be a line what should I do?
just 1 " it can be successful
but when csv file have too may \n and too may “ on line
it's
can't be success
function isallline(){
LineNumber=$1
LineInfo=`echo "$2"|tr -d '\n'`
FileName=$3
LastLineNumber=$4
GetInfo=`echo "$LineInfo"|awk -F '"' '{print NF-1}'`
IsAl=$((GetInfo%2))
if [[ $IsAl != 0 ]]
then
LineNumber=$((LineNumber+1))
LineInfo="$LineInfo""`sed -n ''$LineNumber'p' $FileName|tr -d '\n'`"
if [[ $LineNumber -le $LastLineNumber ]]
then
isallline $LineNumber "$LineInfo" $FileName $LastLineNumber
else
echo "error with not complte'\"'"
fi
else
echo "$LineInfo" >>CSVFile
return $LineNumber
fi
}
function GetCsvFile()
{
FileName=$1
>CSVFile #-- clearn file --
i=1 #-- declare i=1 --
LasetLineNumber=`wc -l $FileName|awk '{print $1 }'`
LineNumber=0 #-- declare LineNumber=0 --
while read LINE #-- read file --
do
getinfo=`echo $LINE|awk -F '"' '{print NF-1}'` #-- get count(") --
if [[ $getinfo != 0 ]]
then
if [[ $LineNumber == 0 ]]
then
isallline $i "$LINE" $FileName LasetLineNumber #-- call function isallline --
LineNumber=$? #-- get function isallline return(LineNumber) --
elif [[ $LineNumber -lt $i ]]
then
isallline $i "$LINE" $FileName LasetLineNumber
LineNumber=$?
fi
fi
if [[ $i -gt $LineNumber ]]
then
echo $LINE >> CSVFile
fi
let i++
done < $FileName
}
Theoretically it's possible to write such regexp, which will be able to parse CSV. But here is brilliant answer why it's more or less practically impossible. You better use specific parser. Actually, almost any linux system has python installed and python includes tooling to parse CSV files
I want to write a script that take 1 command line argument( a directory) and then prompt for 2 number, it will then print out any file(each in a different line) that has the size between that 2 number, this is my script
echo -n "Enter the first number: "
read a
echo -n "Enter the second, bigger number: "
read b
if
[ $b -lt $a ]
then
echo 'The first number must be smaller'
else
echo The files in $1 that are between $a and $b bytes are the following
echo
for var in 'ls $1'
do
if
[ -f $var ]
then
size='ls -l $var | '{ print $5 }''
if
[ $size -le $b && $size -ge $a ]
then
echo $var is $size bytes
fi
fi
done
fi
The problem is after I enter the numbers, it will print out "The files..." and then nothing else. Also, I use Vi to edit it,but the color of last three lines is not quite right(the color should match the first "fi" but it not). Can anyone show me what was wrong? Thank you.
Your immediate problem is that you used single quotes where you wanted command substitution. However, this is the wrong way to iterate over files. You should use pattern matching instead. Your for loop should read
for var in $1/*
do
if [ -f "$var" ]
then
# Check 'man stat' for the correct format string on your system
size=$(stat +%s "$var")
if [ $size -le $b ] && [ $size -ge $a ]
then
echo $var is $size bytes
fi
fi
done
There are a couple of problems here, but the one that I think has you stuck is that the single-quote character (') is used in a couple of places where the backtick character (`) should be used. This is a subtle typographical distinction, so sometimes people that haven't encountered it before don't pick up on the distinction. On my keyboard, you get a backtick character by hitting the key just to the left of the number 1, it is paired with the tilde (~), but your keyboard may be different.
The backtick allows you to assign the output of a command to a variable, for example:
my_variable=`ls - l` # <- uses backtick, assigns output of 'ls -l' command to $my_variable
#As opposed to:
my_variable='ls -l' # <- uses single-quote, makes $my_variable equal to the text "ls -l"
Note, this will also fix your vi issue if you replace the correct single-quotes w/backticks.
As stated by others, use a shebang and use backticks for your commands. Other things that were wrong, ls -l $var | '{ print $5 }' should be ls -l "$1$var" | awk '{ print $5 }' (awk command was missing), and when testing the files you should use the full path to the file like [ -f "$1$var" ] since the user may not be in the same directory as the path they provide as an argument to the script. Another problem is [ $size -le $b && $size -ge $a ]. You can't use the && operator that way, instead use [ $size -le $b ] && [ $size -ge $a ].
These are all the changes I made to your code. Hope it works for you.
echo -n "Enter the first number: "
read a
echo -n "Enter the second, bigger number: "
read b
if [ $b -lt $a ]
then
echo 'The first number must be smaller'
else
echo The files in "$1" that are between "$a" and "$b" bytes are the following
echo
for var in `ls "$1"`
do
if [ -f $1$var ]
then
size=`ls -l "$1$var" | awk '{ print $5 }'`
if [ $size -le $b ] && [ $size -ge $a ]
then
echo "$var" is "$size" bytes
fi
fi
done
fi
#!/bin/bash
a=coop; b=(`echo $a | sed 's/\(.\)/\1\n/g'`)
for i in ${b[#]}
do
echo -n $i
count=$((count+1))
if [ $count = 2 ]; then
echo -e '\e[0;34m'$i
shift
echo -ne $*'\e[0m'
fi
done
Output: cooop (the middle one is in blue). What I want the script to do is show the exact word stored in the variable named "a". But as you can see, another "o" is added next to "p". So how can i go about removing the extra letter?
Try this:
#!/bin/bash
blue='\e[0;34m'
nc='\e[0m'
a=coop
b=($(echo $a | sed 's/\(.\)/\1\n/g'))
count=0
for i in ${b[#]}; do
if [ $count = 2 ]; then
echo -ne "${blue}${i}"
echo -ne "${nc}"
else
echo -n "$i"
fi
count=$((count+1))
done
I am trying to create an if statement that performs an action when it reads a blank line.
I would assume it would be something like this : if ($line=='\n');then
where line is the line that it is reading from a text file. But this is not working.
while read line; do
if [ "$line" = "" ]; then
echo BLANK
fi
done < filename.txt
or a slight variation:
while read line; do
if [ "$line" ]; then
echo NOT BLANK
else
echo BLANK
fi
done < filename.txt
try this:
if [[ "x$line" == "x" ]]; then...
or
if [[ "$line" =~ "^$" ]]; ...
Or also:
grep -q '.' <<< $line
Returns 1 if line is empty, 0 if non-empty