Hello,
Can someone please share a Simple AWK command to append Carriage Return & Line Feed to the end of the file, If the Carriage Return & Line Feed does not exist !
Thanks
Hello,
Can someone please share a Simple AWK command to append Carriage Return & Line Feed to the end of the file, If the Carriage Return & Line Feed does not exist !
Thanks
awk is not a good language for that, being it's not guaranteed to work at all on unterminated lines.
What have you tried?
Hi,
I tried this , I am using cat command which is not efficient
cat source.txt | sed 's/[^[:print:]\r\t]//g' | perl -lpe 's/\x0d$//' > output.txt
Why not the sed
version?
sed '/\r$/!s/$/\r/' source.txt
or
sed 's/\r*$/\r/' source.txt
With awk, try:
awk '{sub(/\r?$/,"\r")}1' file
--
Note: With sed, the use of \r
with the s
command is not standard, it is GNU sed only.
Unix text files have only a linefeed character to indicate a newline.
Perhaps you mean "add a missing linefeed to the end of the file"?
The consider this shell script
#!/bin/sh
# append a missing last newline
prtstdin(){
while IFS= read line; do echo "$line"; done
[ -z "$line" ]] || echo "$line"
}
if [ $# -eq 0 ]
then
prtstdin
else
for arg
do
prtstdin <"$arg"
done
fi
The script can be used like the "cat" program.
Why not use the unix2dos
and dos2unix
programs or (more generally) recode
? They were explicitly designed for the job you (mis-)use other innocent programs for.
I hope this helps.
bakunin
Neither awk
nor sed
have defined behavior according to the standards if the file being processed is not a text file. If an input file contains any characters and the last character in the file is not a <newline> character, that input file is not a text file. (So the code Scrutinizer suggested also depends on GNU extensions to awk
that are not portable and not required by the standards.)
Assuming that all lines in your file are separated by DOS <carriage-return><newline> line separators and you just want to add a <carriage-return><newline> terminator to the last line of a file if it doesn't already exist, and assuming that an empty input file should produce an empty output file (not adding a DOS format empty line), the following POSIX-conforming shell script should be portable to most systems:
{ cat "${1:-file}"; printf '\r\n'; } | awk '
{ if(empty)
print "\r"
if($0 != "\r") {
print
empty = 0
} else empty = 1
}' > "${2:-newfile}"
If you want to try this on a Solaris/SunOS system, change awk
to /usr/xpg4/bin/awk
or nawk
.
This script takes two operands. The first operand is the name of the input file you want to process. The second operand is the name of the output file you want to produce. If neither of these operands are specified on the command line, the input file name defaults to file
and the output file name defaults to newfile
.
Assuming you are using Unix/Linux and are only interested in appending a line terminator to the last line if it doesn't already exist, you could use ed
:
$ echo wq | ed myfile
Newline appended
18
18
$
Andrew
Hi Don, I see where you are going, I may have read the question wrong, I interpreted it as "add a carriage return is it is missing at the end of a line (which ends in linefeed)". So for that, my suggestion does not use extensions - GNU or otherwise - to the standard. I did not mean to also correct a missing newline at the end of the file.
It may be good to note that even though the latter case is not defined by the standards, every implementation of awk
on every OS I know does read the unterminated last line and adds the newline at the end of the file, so IMO this behavior cannot be labeled as a GNU extension.
Like awk
and sed
, ed
has unspecified behavior if the file you are editing is not a text file. The code above may work on some systems, but it is not portable and will not work on all UNIX/Linux/BSD systems!
However, if you change ed
to ex
, the above code should work portably.
Hi Scrutinizer,
Note that the title of this thread (and the description in post #1 in this thread) says "add Carriage Return and Line Feed"; not "add Carriage Return before Line Feed". The description to me sounded like the input file is a DOS text file with <carriage-return><line-feed>(AKA <newline>) line separators that the submitter wants to turn into a DOS text file with complete DOS lines including a <carriage-return><line-feed> terminator at the end of the last line.
The standards say that the behavior is only defined for awk
if all input files are text files. It doesn't make any exception to that requirement for files that are text files except for a partial final line. (The standards do make that exception for the ex
utility.)
I am almost positive that PWB UNIX, UNIX System III, UNIX System V, and the Solaris /usr/xpg4/bin
versions of awk
(at least through early Solaris 10 updates) dropped partial lines without feeding them (with or without an added <newline>) through the script. But, I don't have access to any of those systems to verify it as this point. BSD/macOS awk
does add a <newline> terminator to a partial line at the end of a file so it is an extension that is provided by GNU and other systems.
I have been on this forum long enough that I do not expect exact specifications in the title. I interpreted this to mean a CRLF line ending instead of a LF ending. Do nothing when there is CRLF and change when only LF. It did not make sense to me otherwise.
I know, I already said that I did not try to correct a failing newline at the end of the file with my suggestion. That is not how I interpreted it, I may be wrong..
I don't know about really ancient versions, but I just tested with oawk, nawk, and /usr/xpg4/bin/awk on Solaris 10u11, awk on HPUX and AIX and Tru64. All read the unterminated last line and add a newline.. It may be that on older versions of Solaris it did not do that, but I think the awk utility has not changed in this respect (why would they put effort in "fixing" oawk or nawk if they are only there for legacy reasons?).
Hi Don,
One small change , what if I only need to add the LF if it does not exist at the end of the file , do I just remove the \r from the code ?
Please advise
I think you mean the post#8 script.
Yes, delete all \r so you get '\n' and two times ""
Now echo and sed (where one had a problem to specify a \r in a portable way) can be used:
#!/bin/sh
{ cat "${1:-file}"; echo; } | sed '
$!b
/^$/d
' > "${2:-newfile}"
Is this correct
{ cat "${1:-file}"; printf '\n'; } | awk '
{ if(empty)
print "\n"
if($0 != "\n") {
print
empty = 0
} else empty = 1
}' > "${2:-newfile}"
No. MadeInGermany's suggestion to delete all \r so you get '\n' and two times "" meant exactly what he said... Delete ALL \r
means delete all \r
; not delete the first \r
and change the other two to \n
!
{ cat "${1:-file}"; printf '\n'; } | awk '
{ if(empty)
print ""
if($0 != "") {
print
empty = 0
} else empty = 1
}' > "${2:-newfile}"
Note also that printf '\n';
can be simplified to just be echo;
and still get the same results.
But, using the suggestion proposed by apmcd47 would be more efficient:
printf 'w %s\nq\n' "${2:-newfile}" | ex "${1:-file}"
since we're now creating a UNIX text file instead of a DOS text file.