How can I replace spaces with new lines on an input like:
/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5 etc…
To obtain the following:
/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5
Note
I’m posting this question to help other users, it was not easy to find a useful answer on UNIX SE until I started to type this question. After that I found the following:
Related question
How can I find and replace with a new line?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Use the tr command
echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5" | tr " " "n"
Found on http://www.unix.com/shell-programming-scripting/67831-replace-space-new-line.html
Method 2
In this case I would use printf:
printf '%sn' /path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5
If there are spaces within the one of the paths, you can quote that filepath in order to prevent it from being split on the spaces:
printf '%sn' /path/to/file '/path/to/file with spaces' /path/to/another/file
To transform text in general, tr is your best bet, as covered in an existing answer.
Method 3
Be pragmatic, use GNU sed!!
sed 's/s+/n/g' file
The above says to substitute one or more whitespace characters (s+) with a newline (n).
This is more or less “substitute /one space or more/ for /newline/ globally”.
Method 4
Assuming you have a string with spaces as separators:
newline_separated=${space_separated// /$'n'}
However, you’re probably asking the wrong question. (Not necessarily, for example this might come up in a makefile.) A space-separated list of file names does not really work: what if one of the file names contained spaces?
If a program receives file names as arguments, don’t join them with spaces. Use "[email protected]" to access them one by one. Although echo "[email protected]" prints the arguments with spaces in between, that’s due to echo: it prints its arguments with spaces as separators. somecommand "[email protected]" passes the file names as separate arguments to the command. If you want to print the arguments on separate lines, you can use
printf '%sn' "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="765236">[email protected]</a>"
If you do have space-separated file names and you want to put them in an array to work on them, you can use an unquoted variable expansion to split the value at characters on IFS (you’ll need to disable wildcard expansion with set -f, otherwise glob patterns will be expanded in the value):
space_separated_list='/path/to/file1 /path/to/file2 /path/to/file3'
IFS=' '; set -f
eval "array=($space_separated_list)"
for x in "${array[@]}"; do …
You can encapsulate this in a function that restores the -f setting and the value of IFS when it is done:
split_list () {
local IFS=' ' flags='+f'
if [[ $- = *f* ]]; then flags=; fi
set -f
eval "$1=($2)"
set $flags
}
split_list array '/path/to/file1 /path/to/file2 /path/to/file3'
for x in "${array[@]}"; do …
Method 5
As an alternative to tr from @laconbass, you can also use xargs in this case:
echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5" | xargs -n1
The advantage is that it works even with multiple whitespaces, which tr doesn’t.
Method 6
The question on the title: replace space with new line
The simple, quick, brute force solution is to do exactly that, replace all spaces with new lines:
echo "$input" | tr ' ' 'n'
echo "$input" | sed 'y/ /n/'
echo "$input" | sed 's/ /n/g'
Filenames
But in your question you are listing a list of paths:
echo '/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5' > test.txt
Using the solution above will not work for filenames with spaces (or newlines).
Better
But we can use a two characters delimiter: / (space slash)
That pair of characters could only exist at the beginning of a new (absolute) path:
input='/path/to/file /path/to/file2 /path/to/one space /path/to/new
line /path/to/file5'
$ printf '%sn' "$input" | sed 's# /#n/#g'
/path/to/file
/path/to/file2
/path/to/one space
/path/to/new
line
/path/to/file5
For relative paths, we need to also allow paths that start with ./ or ../:
$ cat test2.txt
/path/to/file /path/to/file2 /path/to/one space /path/to/new
line /path/to/file5 ./path/to/file ../path/to/file2 ./path/to/one space ./path/to/new
line ./path/to/file5 ../path/to/file ../path/to/file2 ../path/to/one space ../path/to/new
line ../path/to/file5
$ sed 's# ([.]{0,2}/)#n1#g' test2.txt
/path/to/file
/path/to/file2
/path/to/one space
/path/to/new
line
/path/to/file5
./path/to/file
../path/to/file2
./path/to/one space
./path/to/new
line
./path/to/file5
../path/to/file
../path/to/file2
../path/to/one space
../path/to/new
line
../path/to/file5
Best
For path names with newlines it is better to quote each pathname.
$ sed -e '1s/^/"/' -e 's# ([.]{0,2}/)#"n"1#g' -e '$s/$/"/' test2.txt
"/path/to/file"
"/path/to/file2"
"/path/to/one space"
"/path/to/new
line"
"/path/to/file5"
"./path/to/file"
"../path/to/file2"
"./path/to/one space"
"./path/to/new
line"
"./path/to/file5"
"../path/to/file"
"../path/to/file2"
"../path/to/one space"
"../path/to/new
line"
"../path/to/file5"
Method 7
Here is how I did it:
echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5" | sed 's/ / '/g
Notice the use of Enter key after backslash in the sed command.
Method 8
Another approach, assuming the line is in a variable called line:
for path in $line;do echo $path;done
This makes use of the fact that Bash splits its arguments on whitespace by default and that echo appends a newline to its input by default.
Method 9
echo word1 word2 ... | sed -e 'y/ /n/;P;D'
is another method to turn single-space-separated words into newline separated.
Method 10
option1:
echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5"|perl -pne "s/ /n/g"
option2:
echo "/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5"|awk '{gsub(/ /,"n",$0);print }'```
output
/path/to/file /path/to/file2 /path/to/file3 /path/to/file4 /path/to/file5
Method 11
Here an example
list=$(cat index.txt | grep href=)
for iterator in $list
do
echo $iterator
done
Here I have string with many links and space between every link, when you use loops it will solve your problem
Method 12
The following script is easy to understand and easy to use.
cat filename | tr ' ' 'n' | tee filename
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0