This question already has answers here:
I just assigned a variable, but echo $variable shows something else
(7 answers)
Closed 5 years ago.
This is the contents of my file file.txt:
header
a
b
c
I have no idea what is going on. This command does not print new lines.
echo -e $(tail -n +2 file.txt)
This prints:
a b c
But if you write it to file you will clearly see new lines:
tail -n +2 file.txt >> new_file.txt
test.txt
a
b
c
How do I force echo to print the new lines? I don't think I can use printf here without making some kind of loop.
Echo statement within quotes give your output with newline terminated lines. Here is the code
echo -e "$(tail -n +2 file.txt)"
Related
This question already has answers here:
Preserving leading white space while reading>>writing a file line by line in bash
(5 answers)
Closed 6 years ago.
I need to create a file by modifying some lines of a source one.
I developed a loop 'while read line; do'. Inside it, the lines I read and don't modify go just:
echo -e "$line" >> "xxxx.c"
My issue is that some of that lines start with '\t', and they won't print the output file.
Example:
while read line;
do
if echo "$line" | grep -q 'timeval TIMEOUT = {25,0};'
then
echo "$line"
fi
Any help? I've tried with the printf command also but without success.
In that case you could just remove "-e" argument from the echo command.
From echo man page:
-e enable interpretation of backslash escapes
This question already has answers here:
What is the difference between "echo" and "echo -n"?
(2 answers)
Closed 6 years ago.
I need to know the meaning of echo -n and this is example: echo -n "" > file.txt. What is the difference between echo and echo -n ?
I read man echo but need more info.
From here:
-n : Do not output a trailing newline.
The > means write it to a file named file.txt (create if doesn't exist).
Here is my code
michal#argon:~$ cat test.txt
1
2
3
4
5
michal#argon:~$ cat test.txt | while read line;do echo $line;done > new.txt
michal#argon:~$ cat new.txt
1
2
3
4
5
I don't know why the command echo $line filtered the space character, I want test.txt and new.txt to be exactly the same.
Please help, thanks.
Several issues with your code.
$parameter outside of " ". Don't.
read uses $IFS to split input line into words, you have to disable this.
UUOC
To summarize:
while IFS= read line ; do echo "$line" ; done < test.txt > new.txt
While the provided answers solves your task at hand, they do not explain why bash and echo "forgot" to print the spaces you have in your string. Lets first make an small example to show the problem. I simply run the commands in my shell, no real script needed for this one:
mogul#linuxine:~$ echo something
something
mogul#linuxine:~$ echo something
something
Two echo commands that both print something right at the beginning of the line, even if the first one had plenty space between echo and something. And now with quoting:
mogul#linuxine:~$ echo " something"
something
Notice, here echo printed the leading spaces before something
If we stuff the string into a variable it work exactly the same:
mogul#linuxine:~$ str=" something"
mogul#linuxine:~$ echo $str
something
mogul#linuxine:~$ echo "$str"
something
Why?
Because the shell, bash in your case, removes space between arguments to commands before passing them on to the sub process. By quoting the strings we tell bash that we mean this literally and it should not mess with out strings.
This knowledge will become quite valuable if you are going to handle files with funny names, like "this is a file with blanks in its name.txt"
Try this --
$ oldIFS="$IFS"; IFS=""; while read line;do echo $line >> new.txt ;done < test.txt; IFS="$oldIFS"
$ cat new.txt
1
2
3
4
5
This question already has answers here:
A variable modified inside a while loop is not remembered
(8 answers)
Closed 4 years ago.
dpkg --list |grep linux-image |grep "ii " | while read line
do
arr=(${line})
let i=i+1
_constr+="${arr[2]} "
done
echo $i
echo ${_constr}
The echo statements outside of the loop do not display the expected variables.
How should I make the contents of the variable propagate outside the loop?
The problem is the pipe, not the loop. Try it this way
let i=0
arr=()
_constr=
while read -r line ; do
arr=("${line}")
let i=i+1
_constr+="${arr[2]} "
done < <(dpkg --list | grep linux-image | grep 'ii ')
echo "$i"
echo "${_constr}"
Pipes are executed in a subshell, as noted by Blagovest in his comment. Using process substitution instead (this is the < <(commands) syntax) keeps everything in the same process, so changes to global variables are possible.
Incidentally, your pipeline could be improved as well
dpkg --list | grep '^ii.*linux-image'
One less invocation of grep to worry about.
This somewhat by-passes your question (and it's a good question), but you can achieve the same results using simply:
_constr=($(dpkg --list | awk '/^ii.*linux-image/{print $2}'))
The ($(cmd)) construct initialises a bash array using the output of the command within.
[me#home]$ echo ${_constr[*]}
linux-image-2.6.35-22-generic linux-image-2.6.35-28-generic linux-image-generic
[me#home]$ echo ${_constr[2]}
linux-image-generic
and you can get the number of elements using ${#_constr[*]}.
[me#home]$ echo ${#_constr[*]}
3
Alternatively, you can move the echo statements inside the subshell:
dpkg --list |grep linux-image |grep "ii " | (
let i=0
declare -a arr
while read line
do
arr=(${line})
let i=i+1
_constr+="${arr[2]} "
done
echo $i
echo ${_constr}
)
Note the insertion of the parenthesis to explicitly define where the subshell begins and ends.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Unix for loop help please?
I am trying to list the names of all the files in a directory separated by a blank line. I was using a for loop but after trying a few examples, none really work by adding blank lines in between. Any ideas?
Is there any command which outputs only the first line of a file in unix? How could I only display the first line?
for i in ls
do
echo "\n" && ls -l
done
for i in ls
do
echo "\n"
ls
done
Use head or sed 1q to display only the first line of a file. But in this case, if I'm understanding you correctly, you want to capture and modify the output of ls.
ls -l | while read f; do
printf '%s\n\n' "$f"
# alternately
echo "$f"; echo
done
IFS="
"
for i in $(ls /dir/name/here/or/not)
do
echo -e "$i\n"
done
To see the first part of a file use head and for the end of a file use tail (of course). The command head -n 1 filename will display the first line. Use man head to get more options. (I know how that sounds).
Use shell expansion instead of ls to list files.
for file in *
do
echo "$file"
echo
if [ -f "$file" ];then
read firstline < "$file"
echo "$firstline" # read first line
fi
done