[BASH] read 'line' issue with leading tabs and virtual line breaks

Heyas

I'm trying to read/display a file its content and put borders around it (tui-cat / tui-cat -t(ypwriter).
The typewriter-part is a 'bonus' but still has its own flaws, but thats for later.

So in some way, i'm trying to rewrite cat using bash and other commands.
But sadly it fails on leading tabs/spaces and virtual line breaks.
http://www.unix.com/shell-programming-and-scripting/257415-bash-getting-semi-tailing-backslash-when-passing-escaped-variables-script.html , didnt help much, and the other 2 found threads regarding 'tailing backslash' as search criteria are also by me and not helping on this subject.

	if [ -f "$arg" ]
	then 	while read content #|sed s,"	","    ",g
		do	# Leading dash
			[ "-" = "${content:0:1}" ] && 
				leadingDASHdummy="--" || 
				leadingDASHdummy=""
			# Tabs, become 4 spaces
			echo "$content" | grep -q "\	" && 
				content="$(echo ${content/\	/\    })"
			# Simple conditions
	#		while echo "$content" | grep -q [&|][&|][[:space:]]'\'
	#		do	remover="${content/\	/\n}"
	#			remover="$(echo $content|head -n1)"
	#			tui-printf -E "$remover"
	#			content="${content%${remover:0:${#remover}-3}}"
	#		done
			
			#tui-echo "$LINENO" "$remover" "$content" #; exit
			
	#		content=$(echo "$content" |
	#				sed s,"\	","\\nt",g |
	#				sed s,"\ "$,"\n",g |
	#				sed s,"	","    ",g |
	#				sed s,^"t","    ",g |
	#				sed s,"t","    ",g
	#				)
			# Tailing backslash
			if echo "$content" | grep [&|][&|]' \'
			then	# Loop through virtual line breaks caused by conditions, doesnt really work either, but doesnt break the border lineup.
				while printf "$content" | grep -q "&& \"
				do	#echo in loop > /dev/stderr
					content2=$(echo "$content" | sed s,"&& \","&& \\",g)
					tui-printf -E $leadingDASHdummy"$content2"
					content="${content/${content2%/}}"
				done
			else	tui-printf -E $leadingDASHdummy"${content}"
			fi
		done<"$arg"
	else	RET=1
		tui-printf -S $RET "File not found: $arg"
	fi

The file i'm displaying is the stats.sh scripts (see: http://www.unix.com/shell-programming-and-scripting/257636-fun-get-some-stats-your-project.html\)
The code above encapsules the script just fine, with the && \ in the lines-section as a single string properly split (by tui-printf [-E]) onto 2 lines (originaly 4 lines ending with && \ ).

I'm trying to 'say':
File-to-Display-snippet:

#	Vars
#
	LINER="########################################"
	#	[ -f "$F" ] && \
	#		COMMENTS=$(( $COMMENTS + $(grep ^"#" "$F" | wc -l) )) && \
	#		LINES=$(( $LINES + $(cat "$F" | wc -l) )) && \
	#		BLANKS=$(( $BLANKS + $(grep ^[[:space:]]$ "$F" | wc -l) ))

Displays as:

# | # Vars                                                                                                       | #
# | #                                                                                                            | #
# | LINER="########################################"                                                             | #
# | #for F in $(find|grep -ve ".git" -ve ".jpg")                                                                 | #
# | #do [ -f "$F" ] && # COMMENTS=$(( $COMMENTS + $(grep ^"#" "$F" | wc -l) )) && # LINES=$(( $L                 | #
# |                INES + $(cat "$F" | wc -l) )) && # BLANKS=$(( $BLANKS + $(grep ^[[:space:]]$ "$F" | wc -l) )) | #
# | #done                                                                                                        | #

Expected:

# | #    Vars                                                                                                    | #
# | #                                                                                                            | #
# |     LINER="########################################"                                                         | #
# |     #for F in $(find|grep -ve ".git" -ve ".jpg")                                                             | #
# |     #do    [ -f "$F" ] && \                                                                                  | #
# |     #        COMMENTS=$(( $COMMENTS + $(grep ^"#" "$F" | wc -l) )) && \                                      | #
# |     #        LINES=$(( $LINES + $(cat "$F" | wc -l) )) && \                                                  | #
# |     #        BLANKS=$(( $BLANKS + $(grep ^[[:space:]]$ "$F" | wc -l) ))                                      | #
# |     #done                                                                                                    | #

tui-printf just prints what is passed (and escaped properly), and puts borders around it.
It does a string splitting, as the single string (all the && \ lines are read as ONE line) doesnt match a single output line .

Basicly i need a way to handle the commented out 'Simple Conditions' section (or those - what i call - virtual linebreaks).

Replacing tui-printf -E with echo , results in a faster display, which lacks the same flaws/issues.

I asume i've used the wrong search criteria/text?
And advice / ideas please?

Thank you

---------- Post updated 08-05-15 at 10:49 ---------- Previous update was 07-05-15 at 11:47 ----------

OK, guess i didnt minimize the code enough.
On the way, figured about the thingsi call virutal linebreaks, the read its -r option solved it.

Sample Text:

#
#	Comment title
#
	Idented text
	[ -z "$EMPTY" ] && \
		echo "yes $EMPTY is empty!"
--hmm
	ident again

Sample Code:

while read -er line;do
	# Leading: DASH		-- not required for 'plain bash'
	#[ "-" = "${line:0:1}" ] && \
	#	leadingDASHdummy="--" || \
	#	leadingDASHdummy=""
	
	# Converting TABS
	line="$(echo "$line"|sed s,'	','    ',g)"	# Doesnt work for leading tabs??
	# Leading: TAB					-- doesnt seem to work either
	[ "	" = "${line:0:1}" ] && \
		line="${line:0:1}    "
	[ "\t" = "${line:0:2}" ] && \
		line="${line:0:2}    "

	echo "${line}"
done<"sample.txt"

Output - Is:

#
#    Commment title
#
Idented text
[ -z "$EMPTY" ] && \
echo "yes $EMPTY is empty!"
--hmm

Output - Expected:

#
#	Commment title
#
	Idented text
	[ -z "$EMPTY" ] && \
		echo "yes $EMPTY is empty!"
--hmm
	ident again

But me still stuck with leading tabs not beeing:
1) Converted to spaces (not required, i thought i'd had more luck to preserve/handle space chars rather than real tabs)
2) Displayed at all :frowning:

Any advices please?

---------- Post updated at 11:10 ---------- Previous update was at 10:49 ----------

When i try to apply: (from: http://www.unix.com/shell-programming-and-scripting/255759-preserve-leading-white-space.html\)

IFS="" while read -er line
do

It fails with:

sh sample.sh 
sample.sh: line 1: while: command not found
sample.sh: line 2: syntax error near unexpected token `do'
sample.sh: line 2: `do'

:confused:

EDIT:
hahaha, just had to put IFS="" on the first line, and the read while on the next..
seems to work now....

IFS=""
while read -r line
do

:b:

---------- Post updated at 11:17 ---------- Previous update was at 11:10 ----------

Just happy:

:) tmp $  ../prjs/tui/bin/tui-cat sample.txt 
# | #                                                                                                            | #
# | #    Commment title                                                                                          | #
# | #                                                                                                            | #
# |     Idented text                                                                                             | #
# |     [ -z "$EMPTY" ] && \                                                                                     | #
# |         echo "yes $EMPTY is empty!"                                                                          | #
# | --hmm                                                                                                        | #
# |     ident again                                                                                              | #
 tmp $ 

:dance: :cool:

IFS="" outside the while block has a lasting effect!
In most cases you want the effect only for the read command:

while IFS="" read -r line
do
1 Like

True, inside the script.
As far i can tell, there is no lasting effect for outside the script:

:) tmp $  ../prjs/tui/bin/tui-cat -d 0.01 sample.txt 
|| #                                                                                                              ||
|| #    Commment title                                                                                            ||
|| #                                                                                                              ||
||     Idented text                                                                                               ||
||     [ -z "$EMPTY" ] && \                                                                                       ||
||         echo "yes $EMPTY is empty!"                                                                            ||
|| --hmm                                                                                                          ||
||     ident again                                                                                                ||
||                                                                                                                ||
+ tmp $ echo ":$IFS:"
: 	
:

Seems right'ish to me.

EDIT:
I used a single IFS="" for both modes, cat and typewriter (the example above, -d 0.001 is the delay with each char (text only, not borders) is shown.
But changing anyway, for better practice, thank you for pointing out.