You can set the internal field separator (IFS) variable, and then let it parse into an array. When this happens in a command, then the assignment to only takes place to that single command's environment (to IFS ). It then parses the input according to the read variable value into an array, which we can then iterate over.IFS
This example will parse one line of items separated by , pushing it into an array:;
IFS=';' read -ra ADDR <<< "$IN"
for i in "${ADDR[@]}"; do
# process "$i"
done
This other example is for processing the whole content of , each time one line of input separated by $IN:;
while IFS=';' read -ra ADDR; do
for i in "${ADDR[@]}"; do
# process "$i"
done
done <<< "$IN"
Use cut:
echo 'someletters_12345_moreleters.ext' | cut -d'_' -f 2
More generic:
INPUT='someletters_12345_moreleters.ext'
SUBSTRING=$(echo $INPUT| cut -d'_' -f 2)
echo $SUBSTRING
$ cat > test.yaml << EOF
Line 1
Line 2
Line 3
EOF
$ cat test.yaml
The symbol refers to create a > filetest.yaml
You can leverage 's ability to read from stdin combined with it's ability to read multiple files to achieve this.cat
~$ cat file.txt
Hello from file.txt
~$ echo "My final line" | cat file.txt -
Hello from file.txt
My final line
You can also prepend a line, as such:
~$ echo "My final line" | cat - file.txt
My final line
Hello from file.txt
Note that you are not limited to a single line. will read from stdin until it reaches EOF. You can pass the output from cat, for example, to prepend or append to the output of curl.cat
~$ curl -s http://perdu.com | cat file.txt -
Hello from file.txt
<html><head><title>Vous Etes Perdu ?</title></head><body><h1>Perdu sur l'Internet ?</h1><h2>Pas de panique, on va vous aider</h2><strong><pre> * <----- vous êtes ici</pre></strong></body></html>
Your problem seems not to be how here-documents work, as you have correctly described their use in script files. It seems that you don’t understand their interactive use. The following is a (much simplified) crash course which will hopefully clarify the matter for you.
Shells, like all Unix processes in general, have input and output streams to read and write data, to and fro. They have at least one input stream (called ) and two output streams (stdin and stdout), but they can open and close as many as they want, for reading and for writing (mostly, to read from files or write to them). What processes do with their streams depends on them. stderr, for instance, when called without arguments, copies its cat to stdin. Shells usually interpret their input streams as commands to be executed (and set up input and output streams for those commands according to some syntax). stdout
Where do input data come from? They can come from other processes sending them, they can be read from files, or they can be typed directly by the user, which is the most normal situation for a shell’s . In this case, there must be another program taking the user input and loading it into the stream. Such a program is called a stdin and in this case we say that the stream is attached to a tty (the tty is different from the terminal emulation program which provides a window for it, but you can also, broadly speaking, say that the stream is attached to a terminal.) tty
Shells know when their is attached to a stdin and behave differently, for instance printing a prompt when waiting for input, but there are really not many other differences. A prompt is usually something like tty. Its exact contents can be defined by altering the variable user@host:current_path$. A usual convention is that it ends with PS1 when you are a normal user, and with $ when you are #.root
When you execute a script, the shell attaches an input stream to the file containing it, and reads commands from it. If one of the commands contains a here-document, that is, something like , this means: from now on, up to a line containing exactly only this terminator, stop interpreting the stream data as commands and pass them on to the <<END of the command you are going to execute (stdin in your case), possibly with some mangling that will not bother us now. This is what you already know, albeit possibly in another perspective.cat
When input is attached to a , a here-document means the same: stop interpreting the stream data as commands and pass them on to the tty of the command you are going to execute, up to the terminator. The only difference is, print a prompt when waiting for input; this prompt is different from the one the shell would print if it were going to interpret the input data as commands, just to let you know that they will be passed on. It is defined by the variable stdin and its value defaults to PS2. You see it at the beginning of every line after typing >, until the terminator is read, when the shell resumes its normal behavior, prints its cat file > file << "END"-prompt and waits for input to be interpreted as commands.PS1
Compare the two here documents in the following example:
(yeti@darkstar:6)~/wrk/tmp$ cat ./xyzzy
#!/bin/bash
cat << EOF
Version 1 - Today is $(date)
EOF
cat << 'EOF'
Version 2 - Today is $(date)
EOF
(yeti@darkstar:6)~/wrk/tmp$ ./xyzzy
Version 1 - Today is Sa 21. Jun 08:51:38 CEST 2014
Version 2 - Today is $(date)
There is no difference, and no particular meaning to those two strings, or any others. It's just an arbitrary terminator and you can use almost any string you like.
Of course, the data itself can't contain that particular line, so if your data contains e.g. a shell script that has another here-doc, you'll need to use different terminators in both. Using somewhat descriptive strings may be useful for any future readers of the script.
E.g.
cat > test.sh <<END_OF_SCRIPT
cat <<EOF
hello
EOF
END_OF_SCRIPT
produces which, when executed through the shell prints test.sh.hello
There is a difference if you quote the terminator in the line that starts the here-doc, though, it'll prevent expansions in the here-doc data. This prints , not whatever the value of the variable is:$i
cat << 'EOF'
$i
EOF
See also:
awk '{$1=$1;print}'
or shorter:
awk '{$1=$1};1'
Would trim leading and trailing space or tab characters1 and also squeeze sequences of tabs and spaces into a single space.
That works because when you assign something to one of the fields, rebuilds the whole record (as printed by awk) by joining all fields (print, ..., $1) with $NF (space by default).OFS
To also remove blank lines, change it to (where awk '{$1=$1};NF' tells NF to only print the records for which the awkumber of Nields is non-zero). Do not do as sometimes suggested as that would also remove lines whose first field is any representation of F supported by 0 (awk, 0, 00...)-0e+12
1(and possibly other blank characters depending on the locale and the implementation)awk