1

I build ord and chr functions and they work just fine. But if I take a file that contains \n, for example:

hello
CHECK THIS HIT
YES

when I ord everything I don't get any new line values. Why is that? I'm writing in Bash.

Here is the code that I am using:

function ord { 
    ordr="`printf "%d\n" \'$1`" 
}

TEXT="`cat $1`"
for (( i=0; i<${#TEXT}; i++ )) 
do 
    ord "${TEXT:$i:1}" 
    echo "$ordr" 
done
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
JhonaBona99
  • 33
  • 1
  • 4
  • 2
    Show your `ord` and `chr` functions, and how you use them with your file! – gniourf_gniourf Feb 12 '15 at 11:47
  • @lurker So I find out that the problem it's in how I store the file content I do STR=`cat file1` The newline values is absorbed like you said.. How can I store in a var file content – JhonaBona99 Feb 12 '15 at 11:58
  • You're wrong: `STR=$(cat file1)` _doesn't “absorb” (whatever that means) newline values_. You're probably missing quotes, which is a, sadly, too common mistake. Show your code! – gniourf_gniourf Feb 12 '15 at 12:05
  • Look on this code: STR=$(cat file1) echo $STR hello CHECK THIS HIT YES It's all in one line. – JhonaBona99 Feb 12 '15 at 12:12
  • 1
    That's because you're doing `echo $STR`, not `echo "$STR"`. – Tom Fenech Feb 12 '15 at 12:14
  • Amazing, Thanks a lot ! Can you explain me why the quotes make the difference ? – JhonaBona99 Feb 12 '15 at 12:15
  • @lurker with `STR=$(cat file1)`, the newline characters _are not_ translated into spaces. Please learn how to check the content of a variable: either with `declare -p STR` or `printf '%q\n' "$STR"`, or, for a quick overview `echo "$STR"` _with quotes_. The only character that will get _absorbed_ is the null byte, as a Bash variable can't hold the null byte. – gniourf_gniourf Feb 12 '15 at 12:17
  • @gniourf_gniourf I had done, `echo $STR | od -cx` and saw spaces instead of newlines. Without the quotes. It was just illustrating that using `echo` without the quotes translated to spaces. – lurker Feb 12 '15 at 12:18
  • @JhonaBona99 see for example my answer here: http://stackoverflow.com/questions/25470652/linux-bash-redirect-a-string-to-a-file/25470688#25470688 – Tom Fenech Feb 12 '15 at 12:18
  • Another question: When I'm making for loop and ord ${TEXT:$i:1} I never catch the \n why is that? – JhonaBona99 Feb 12 '15 at 12:20
  • did you read the answer? `ord "${TEXT:$i:1}"` – Tom Fenech Feb 12 '15 at 12:22
  • @lurker: without the quotes, you also have pathname expansion! `STR='*'; echo $STR`. Always quotes your variables unless you want nasty things to happen `:D`. – gniourf_gniourf Feb 12 '15 at 12:22
  • 1
    @gniourf_gniourf yes, I understand that. I deleted my comment to avoid confusion for the OP, but I was just illustrating that, without the quotes, there are issues. – lurker Feb 12 '15 at 12:24
  • @TomFenech It's not work with the quote either.. – JhonaBona99 Feb 12 '15 at 12:24
  • @JhonaBona99 just to reiterate: unless you show your code, it's hard to determine what you're doing wrong. But `${TEXT:$i:1}` should give you the new line if the index of the newline is indeed at `$i`. – lurker Feb 12 '15 at 12:25
  • 1
    @JhonaBona99 that's very likely because your `ord` command is badly written and misses lots of quotes all over the place! ***Please show your code***. – gniourf_gniourf Feb 12 '15 at 12:25
  • 2
    Your question was posted 41 minutes ago. 38 minutes ago I asked you to show your code. We have wasted so much time because you don't want to cooperate! Your question has 4 votes to close and 3 downvotes. Don't you understand that the only thing we're asking you to help you is that you show your code??? Edit your post and include your `ord` function and the way you use it. – gniourf_gniourf Feb 12 '15 at 12:26
  • Thanks for sharing your code at last, although I dispute the claim that it works just fine. There are a number of errors in that code, including some which I suspect means that it fails to run at all. I suggest that you go to http://www.shellcheck.net/ and deal with them, then [edit] your question. – Tom Fenech Feb 12 '15 at 12:50
  • 1
    @TomFenech I guess that the missing backticks were artifacts of the text format in the comment. I fixed that `:D`. – gniourf_gniourf Feb 12 '15 at 13:14

1 Answers1

6

Your ord function is really weird. Maybe it would be better to write it as:

function ord { 
    printf -v ordr "%d" "'$1"
}

Then you would use it as:

TEXT=$(cat "$1")
for (( i=0; i<${#TEXT}; i++ )); do 
    ord "${TEXT:$i:1}" 
    printf '%s\n' "$ordr"
done

This still leaves two problems: you won't be able to have null bytes and you won't see trailing newlines. For example (I called your script banana and chmod +x banana):

$ ./banana <(printf 'a\0b\n')
97
98

Two problems show here: the null byte is removed from Bash in the TEXT=$(cat "$1") part, as a Bash variable can't contain null bytes. Moreover, this step also trims trailing newlines.

A more robust approach would be to use read:

while IFS= read -r -n 1 -d '' char; do
    ord "$char"
    printf '%s\n' "$ordr"
done < "$1"

With this modification:

$ ./banana <(printf 'a\0b\n')
97
0
98
10

Note that this script will depend on your locale. With my locale (LANG="en_US.UTF-8):

$ ./banana <(printf 'a\0ℂ\n')
97
0
8450
10

whereas:

$ LANG= ./banana <(printf 'a\0ℂ\n')
97
0
226
132
130
10

That's to show you that Bash doesn't read bytes, but characters. So depending on how you want Bash to treat your data, set LANG accordingly.


If your script only does that, it's much simpler to not use an ord function at all:

#!/bin/bash

while IFS= read -r -n 1 -d '' char; do
    printf '%d\n' "'$char"
done < "$1"

It's that simple!

gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104