Insert LineFeed into string? ( echo -e ) [ Solved ]

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Post Reply
Message
Author
potong
Posts: 88
Joined: Fri 06 Mar 2009, 04:01

#16 Post by potong »

technosaurus: printf can replace echo (and I think it's posix too):

Code: Select all

# string='a,b,c,d,e'
# echo -e "${string//,/\n}"
a
b
c
d
e
# printf "${string//,/\n}\n"
a
b
c
d
e
Of course you have to remember to add your own newline!
For those that like to work with arrays (non-posix?)

Code: Select all

# IFS=, read -ra array <<<"$string"
# for i in "${!array[@]}";do printf "\${array[$i]}=\"${array[$i]}\"\n";done
${array[0]}="a"
${array[1]}="b"
${array[2]}="c"
${array[3]}="d"
${array[4]}="e"
# new_string=$(IFS=$'\n';printf "${array[*]}")
# printf "$new_string\n"
a
b
c
d
e
Basically this uses the $IFS variable to split the string into an array. Then uses it again to combine back into a string

Code: Select all

# another_string=$(printf "%s" "${array[@]/%/\n}")
# printf "$another_string"
a
b
c
d
e
Another way to achieve the same ends is to append a newline to each element of an array and then print the each element of the array.
But beware there is a gotcha:

Code: Select all

# yet_another_string=$(IFS=;printf "${array[*]/%/\n}")
# printf "$yet_another_string"
a
b
c
d
e# printf "$yet_another_string"|od -acx
0000000   a  nl   b  nl   c  nl   d  nl   e nul
          a  \n   b  \n   c  \n   d  \n   e  \0
        0a61 0a62 0a63 0a64 0065
0000011
The first printf "$string" chomps the last newline!! So use:

Code: Select all

# yet_another_string=$(IFS=;printf "%s" "${array[*]/%/\n}")
# printf "$yet_another_string"|od -acx
0000000   a  nl   b  nl   c  nl   d  nl   e  nl
          a  \n   b  \n   c  \n   d  \n   e  \n
        0a61 0a62 0a63 0a64 0a65
0000012
HTH

Potong

big_bass
Posts: 1740
Joined: Mon 13 Aug 2007, 12:21

#17 Post by big_bass »

this adds a new line to every character in a string

Code: Select all

string="Vertical"
echo -n "string" | sed 's/./&@/g '| tr '@' '\n' 
you can pass the octal code number too but more difficult to remember but very powerful combined with this http://www.asciitable.com/

Code: Select all

string="Vertical"
echo -n "string" | sed 's/./&@/g '| tr '@' '\012' 

this removes the last space from the string

Code: Select all

string="Vertical"
echo -n "string" | sed 's/./&@/g; s/@$//' | tr '@' '\012'



Note that the "sed" command adds a '@' character after every character,
except at the end of the string.
The "tr" then replaces the '@' characters with newlines.
It also assumes the input text does not end with a newline,
which would cause an extra blank space to be added at the
bottom

*I got and use that snippet from imagemajick



if you play with octal codes you can do many cool things the
forum doesnt show the format of these but they work
string="Verticaltabs"
echo -n "string" | sed 's/./&@/g '| tr '@' '\013'


string="bigtabs"
echo -n "string" | sed 's/./&@/g '| tr '@' '\011'



Joe

potong
Posts: 88
Joined: Fri 06 Mar 2009, 04:01

#18 Post by potong »

Nearly forgot!

Code: Select all

# yas=$(set a b c d e;printf "%s\n" "$@")
# printf "$yas\n"
a
b
c
d
e
For an array-like method good for functions.
Lastly... "%s\n" can be any kind of format you like, check it out here.

HTH

Potong

p.s. big_bass: if your using gnu sed

Code: Select all

# sed 's/,/\n/g' <<<"a,b,c,d,e"
a
b
c
d
e
works too!

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#19 Post by technosaurus »

yes with some shells it ($@) is the only way to get array-like behavior (busybox ash and hush included)

ex

#print $3 - $8
echo ${@:3:6}

#print last 5 vars
POS=$(($#-5))
echo ${@:$POS:5}

or here is a practice script that I wrote to implement tail
it changes the separator so that set will store each line as a separate variable (line 1 is $1 and last line is $#)

Code: Select all

#!/bin/ash

tail_help(){
echo "tail -[cnqv] files"
exit
}

[ $1 ] || tail_help

while ([ $# > 0 ]) do
	case $1 in
	-h|--help)tail_help;;
	--version)echo "tail v0.0";exit;;
	-c)BYTES=${2};shift;shift;;
	--bytes=*)BYTES=${1%=*};shift;;
	-n)LINES=${2};shift;shift;;
	--lines=*)LINES=${1%=*};shift;;
	-q|--quiet|--silent)QUIET=1;shift;;
	-v|--verbose)VERBOSE=1;shift;;
	#todo -f and -s
	*)[ -f ${1} ] && break || tail_help;;
	esac
done

#for -f while goes here
for FILE in $@; do
	HEADER="==> "$FILE" <=="
	[ ! $QUIET ] && [ $# -gt 1 ] || [ $VERBOSE ] && echo $HEADER
#	while read LINE || [ $LINE ] && echo $LINE && LINE=""; do echo $LINE; done <"${FILE}"
	A=`while read -r LINE; do echo $LINE; done <"${FILE}";echo $LINE`
	[ ${#A} -lt 1 ] && echo && continue
	if [ $BYTES ];then
		#for -f compare BYTES to new $#A - old $#A and print the lesser
		i=$((${#A}-$BYTES))
		echo "${A:$i:$BYTES}"
	else
		OLDIFS=$IFS
		IFS="
"
		set ${A}
		#for -f get size here and compare to last
		LINES=${LINES:-10}
		shift $(($#-$LINES))
		for LINE in $@; do
			echo "${LINE}"
		done
		IFS=$OLDIFS
	fi

done
you can do a lot with IFS, set and string manipulation without having to use anything external to the shell
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

big_bass
Posts: 1740
Joined: Mon 13 Aug 2007, 12:21

#20 Post by big_bass »

Potong

p.s. big_bass: if your using gnu sed
Code:
# sed 's/,/\n/g' <<<"a,b,c,d,e"
a
b
c
d
e
works too!
hey potong nice thanks and without commas needed to separate
like this even more compact code

Code: Select all

sed 's/./&\n/g' <<<"string" 

for every single character show the single character and a new line


Joe

Post Reply