LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   CAT giving unexpected results (https://www.linuxquestions.org/questions/programming-9/cat-giving-unexpected-results-4175455006/)

danielbmartin 03-21-2013 10:29 AM

CAT giving unexpected results
 
Have: a character matrix such as ...
Code:

abcde
fghij
klmno
pqrst

Have: a bash variable, a character string such as ...
Code:

NewRow='NEWROW'
Want: to attach the string as a new row at the top of the matrix.
This code ...
Code:

echo; echo; echo "Add a row to the top of a matrix."
echo "Input ..."; cat $InFile
echo; echo "Result ..."
NewRow='NEWROW'
 cat <<< $NewRow \
|cat - $InFile

... produces this result ...
Code:

Add a row to the top of a matrix.
Input ...
abcde
fghij
klmno
pqrst

Result ...
NEWROW
abcde
fghij
klmno
pqrst

... as expected. All good.


Now, a variation on the theme.....

Have: the same matrix and the same character string.

This code (which appears to be the inverse of that shown above) ...
Code:

echo "Add a row to the bottom of a matrix."
echo "Input ..."; cat $InFile
echo; echo "Result ..."
NewRow='NEWROW'
 cat $InFile  \
|cat - <<< $NewRow

... produces this unexpected result ...
Code:

Add a row to the bottom of a matrix.
Input ...
abcde
fghij
klmno
pqrst

Result ...
NEWROW

Please explain.

Note 1) There are other ways to "tack on" a row to the top or bottom of a matrix, such as sed.
I'm not looking for alternate solutions, but only an explanation for why cat failed.

Note 2) Please don't chide me for a "useless" cat. That's not the point of the question.

Daniel B. Martin

grail 03-21-2013 11:00 AM

Its late so have not thought this all the way through, however, the issue is not cat but rather your use of re-directions and which order they are being processed in.

I'll have another look in the morning in case no one else elaborates or you don't find the solution using my information :)

ntubski 03-21-2013 11:54 AM

Quote:

Originally Posted by danielbmartin (Post 4916020)
Code:

cat $InFile  \
|cat - <<< $NewRow


There is only a single stdin stream, you are trying to connect it to 2 things. The same problem as:
Code:

cat < file1 < file2

PTrenholme 03-21-2013 12:10 PM

And, to get the result you want, with minimal modification to your logic, use
Code:

echo; echo; echo "Add a row to the top of a matrix."
echo "Input ..."; cat $InFile
echo; echo "Result ..."
NewRow='NEWROW'
 tac <<< $NewRow | tac - $InFile | tac


mina86 03-21-2013 12:47 PM

Uh… What's wrong with:
Code:

printf '%s\n' "$NewRow" | cat - "$InFile"
Also, remember to quote your variables. If you aren't sure if you have to, quote.

danielbmartin 03-21-2013 02:45 PM

Quote:

Originally Posted by mina86 (Post 4916092)
Uh… What's wrong with:
Code:

printf '%s\n' "$NewRow" | cat - "$InFile"

Your code plants the NewRow at the top of the matrix, not the bottom.

Repeating from the original post:
Quote:

I'm not looking for alternate solutions, but only an explanation for why cat failed.

danielbmartin 03-21-2013 02:52 PM

Quote:

Originally Posted by PTrenholme (Post 4916074)
And, to get the result you want, with minimal modification to your logic, use
Code:

echo; echo; echo "Add a row to the top of a matrix."
echo "Input ..."; cat $InFile
echo; echo "Result ..."
NewRow='NEWROW'
 tac <<< $NewRow | tac - $InFile | tac


Your code works but I hesitate to use tac three times when one sed does the same job.

Repeating from the original post:
Quote:

I'm not looking for alternate solutions, but only an explanation for why cat failed.
Daniel B. Martin

colucix 03-21-2013 04:03 PM

Indeed, as ntubski explained, the problem is the double redirection of the standard input from the pipe and from the here string. The reason is that the last one supersedes the preceding one. In this case the cat command doesn't receive input from the pipe anymore, but only from the here string.

ntubski 03-21-2013 06:53 PM

Quote:

Originally Posted by danielbmartin (Post 4916157)
Your code plants the NewRow at the top of the matrix, not the bottom.

Oh, I missed that you were trying to do that too.

Quote:

Note 2) Please don't chide me for a "useless" cat. That's not the point of the question.
Without the distraction of the redundant cat it's easier to see what the correct inverse is:
Code:

# stdin ("NEWROW") then $InFile
cat - "$InFile" <<< "$NewRow"
# $InFile then stdin
cat "$InFile" - <<< "$NewRow"


danielbmartin 03-21-2013 08:56 PM

Quote:

Originally Posted by ntubski (Post 4916259)
Without the distraction of the redundant cat it's easier to see what the correct inverse is:
Code:

# stdin ("NEWROW") then $InFile
cat - "$InFile" <<< "$NewRow"
# $InFile then stdin
cat "$InFile" - <<< "$NewRow"


Excellent! Thank you for these crisp and instructive gems!

Thank you also to everyone who contributed to this thread.

SOLVED

Daniel B. Martin

danielbmartin 03-21-2013 09:33 PM

Quote:

Originally Posted by mina86 (Post 4916092)
... remember to quote your variables. If you aren't sure if you have to, quote.

Thank you, this is good advice.
Misplaced or missing quotes have caused many a stumble.

Daniel B. Martin


All times are GMT -5. The time now is 03:21 PM.