How to remove a newline from a string in Bash
BashVariablesBash Problem Overview
I have the following variable.
echo "|$COMMAND|"
which returns
|
REBOOT|
How can I remove that first newline?
Bash Solutions
Solution 1 - Bash
Under [tag:bash], there are some bashisms:
The tr
command could be replaced by //
bashism:
COMMAND=$'\nREBOOT\r \n'
echo "|${COMMAND}|"
|
OOT
|
echo "|${COMMAND//[$'\t\r\n']}|"
|REBOOT |
echo "|${COMMAND//[$'\t\r\n ']}|"
|REBOOT|
See Parameter Expansion and QUOTING in bash's man page:
man -Pless\ +/\/pattern bash
man -Pless\ +/\\\'string\\\' bash
man -Pless\ +/^\\\ *Parameter\\\ Exp bash
man -Pless\ +/^\\\ *QUOTING bash
Further...
As asked by @AlexJordan, this will suppress all specified characters. So what if $COMMAND
do contain spaces...
COMMAND=$' \n RE BOOT \r \n'
echo "|$COMMAND|"
|
BOOT
|
CLEANED=${COMMAND//[$'\t\r\n']}
echo "|$CLEANED|"
| RE BOOT |
shopt -q extglob || { echo "Set shell option 'extglob' on.";shopt -s extglob;}
CLEANED=${CLEANED%%*( )}
echo "|$CLEANED|"
| RE BOOT|
CLEANED=${CLEANED##*( )}
echo "|$CLEANED|"
|RE BOOT|
Shortly:
COMMAND=$' \n RE BOOT \r \n'
CLEANED=${COMMAND//[$'\t\r\n']} && CLEANED=${CLEANED%%*( )}
echo "|${CLEANED##*( )}|"
|RE BOOT|
Note: [tag:bash] have extglob
option to be enabled (shopt -s extglob
) in order to use *(...)
syntax.
Solution 2 - Bash
echo "|$COMMAND|"|tr '\n' ' '
will replace the newline (in POSIX/Unix it's not a carriage return) with a space.
To be honest I would think about switching away from bash to something more sane though. Or avoiding generating this malformed data in the first place.
Hmmm, this seems like it could be a horrible security hole as well, depending on where the data is coming from.
Solution 3 - Bash
Clean your variable by removing all the carriage returns:
COMMAND=$(echo $COMMAND|tr -d '\n')
Solution 4 - Bash
Using bash
:
echo "|${COMMAND/$'\n'}|"
(Note that the control character in this question is a 'newline' (\n
), not a carriage return (\r
); the latter would have output REBOOT|
on a single line.)
Explanation
Uses the Bash Shell Parameter Expansion ${parameter/pattern/string}
:
> The pattern is expanded to produce a pattern just as in filename expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. [...] If string is null, matches of pattern are deleted and the / following pattern may be omitted.
Also uses the $''
ANSI-C quoting construct to specify a newline as $'\n'
. Using a newline directly would work as well, though less pretty:
echo "|${COMMAND/
}|"
Full example
#!/bin/bash
COMMAND="$'\n'REBOOT"
echo "|${COMMAND/$'\n'}|"
# Outputs |REBOOT|
Or, using newlines:
#!/bin/bash
COMMAND="
REBOOT"
echo "|${COMMAND/
}|"
# Outputs |REBOOT|
Solution 5 - Bash
What worked for me was echo $testVar | tr "\n" " "
Where testVar contained my variable/script-output
Solution 6 - Bash
Adding answer to show example of stripping multiple characters including \r using tr and using sed. And illustrating using hexdump.
In my case I had found that a command ending with awk print of the last item |awk '{print $2}'
in the line included a carriage-return \r as well as quotes.
I used sed 's/["\n\r]//g'
to strip both the carriage-return and quotes.
I could also have used tr -d '"\r\n'
.
Interesting to note sed -z
is needed if one wishes to remove \n line-feed chars.
$ COMMAND=$'\n"REBOOT"\r \n'
$ echo "$COMMAND" |hexdump -C
00000000 0a 22 52 45 42 4f 4f 54 22 0d 20 20 20 0a 0a |."REBOOT". ..|
$ echo "$COMMAND" |tr -d '"\r\n' |hexdump -C
00000000 52 45 42 4f 4f 54 20 20 20 |REBOOT |
$ echo "$COMMAND" |sed 's/["\n\r]//g' |hexdump -C
00000000 0a 52 45 42 4f 4f 54 20 20 20 0a 0a |.REBOOT ..|
$ echo "$COMMAND" |sed -z 's/["\n\r]//g' |hexdump -C
00000000 52 45 42 4f 4f 54 20 20 20 |REBOOT |
And this is relevant: https://stackoverflow.com/questions/3091524/what-are-carriage-return-linefeed-and-form-feed
- CR == \r == 0x0d
- LF == \n == 0x0a
Solution 7 - Bash
If you are using bash with the extglob option enabled, you can remove just the trailing whitespace via:
shopt -s extglob
COMMAND=$'\nRE BOOT\r \n'
echo "|${COMMAND%%*([$'\t\r\n '])}|"
This outputs:
|
RE BOOT|
Or replace %% with ## to replace just the leading whitespace.
Solution 8 - Bash
You can simply use echo -n "|$COMMAND|"
.
Solution 9 - Bash
To address one possible root of the actual issue, there is a chance you are sourcing a crlf file.
CRLF Example:
.env (crlf)
VARIABLE_A="abc"
VARIABLE_B="def"
run.sh
#!/bin/bash
source .env
echo "$VARIABLE_A"
echo "$VARIABLE_B"
echo "$VARIABLE_A $VARIABLE_B"
Returns:
abc
def
def
If however you convert to LF:
.env (lf)
VARIABLE_A="abc"
VARIABLE_B="def"
run.sh
#!/bin/bash
source .env
echo "$VARIABLE_A"
echo "$VARIABLE_B"
echo "$VARIABLE_A $VARIABLE_B"
Returns:
abc
def
abc def