开发者

sed: how to replace CR and/or LF with "\r" "\n", so any file will be in one line

I have files like

aaa

bbb

ccc

I need them to sed into aaa\r\nbbb\r\nccc

It should work either for unix and windows replacing them with \r or开发者_如何转开发 \r\n accordingly

The problem is that sed adds \n at the end of line but keeps lines separated. How can I fix it?


These two commands together should do what you want:

sed ':a;N;$!ba;s/\r/\\r/g'
sed ':a;N;$!ba;s/\n/\\n/g'

Pass your input file through both to get the output you want. Theres probably a way to combine them into a single expression.

Stolen and Modified from this question:

How can I replace a newline (\n) using sed?


It's possible to merge lines in sed, but personally, I consider needing to change line breaks a sign that it's time to give up on sed and use a more powerful language instead. What you want is one line of perl:

perl -e 'undef $/; while (<>) { s/\n/\\n/g; s/\r/\\r/g; print $_, "\n" }'

or 12 lines of python:

#! /usr/bin/python
import fileinput
from sys import stdout
first = True
for line in fileinput.input(mode="rb"):
    if fileinput.isfirstline() and not first:
        stdout.write("\n")
    if line.endswith("\r\n"): stdout.write(line[:-2] + "\\r\\n")
    elif line.endswith("\n"): stdout.write(line[:-1] + "\\n")
    elif line.endswith("\r"): stdout.write(line[:-1] + "\\r")
    first = False
if not first: stdout.write("\n")

or 10 lines of C to do the job, but then a whole bunch more because you have to process argv yourself:

#include <stdio.h>

void process_one(FILE *fp)
{
    int c;
    while ((c = getc(fp)) != EOF)
        if (c == '\n') fputs("\\n", stdout);
        else if (c == '\r') fputs("\\r", stdout);
        else putchar(c);
    fclose(fp);
    putchar('\n');
}

int main(int argc, char **argv)
{
    FILE *cur;
    int i, consumed_stdin = 0, rv = 0;
    if (argc == 1) /* no arguments */
    {
        process_one(stdin);
        return 0;
    }

    for (i = 1; i < argc; i++)
    {
        if (argc[i][0] == '-' && argc[i][1] == 0)
        {
            if (consumed_stdin)
            {
                fputs("cannot read stdin twice\n", stderr);
                rv = 1;
                continue;
            }
            cur = stdin;
            consumed_stdin = 1;
        }
        else
        {
            cur = fopen(ac[i], "rb");
            if (!cur)
            {
                perror(ac[i]);
                rv = 1;
                continue;
            }
        }
        process_one(cur);
     }
     return rv;
 }


awk '{printf("%s\\r\\n",$0)} END {print ""}' file


tr -s '\r' '\n' <file | unix2dos

EDIT (it's been pointed out that the above misses the point entirely! •///•)

tr -s '\r' '\n' <file | perl -pe 's/\s+$/\\r\\n/'

The tr gets rid of empty lines and dos line endings. The pipe means two processes—good on modern hardware.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜