1

很抱歉这个简单的问题,但我已经失明了四天的学习和尝试,似乎无法找到正确的语法。

在 cygwin 上使用 sed,我试图用另一个不可打印的字符替换一个不可打印的 ASCII 字符。

这是我的源文件,使用大写文本 [在方括号内] 表示不可打印的 ascii 字符:

myfile.txt:

line one[LF]
line two[LF]
line three[LF]
[SUBSTITUTE][LF]
line four{LF]
line five[LF]
line six[LF]
.
.
.

我想用 TAB 替换 LF。

由于 LF 是十六进制 0A 而制表符是十六进制 09,所以我基本上尝试过:

sed -i 's/\x0A/\x09/g' myfile.txt

这不会改变文件中的任何内容。

当然,我尝试了不同的开关,例如 -b、-e 和 -r,有括号和没有括号,有和没有 /g,额外的反斜杠和没有反斜杠,八进制和十进制符号,一直到精灵符文,绝对没有成功。

我读了一些使用“回声”而不是文件作为来源的答案,他们只是让我感到困惑并且没有用。

其他示例使用“作弊”,例如实际单词 TAB,但它们阻止我学习使用数字的语法,因此我可以将其应用于其他不可打印的字符,而不仅仅是 TAB。

当我尝试“文件”命令时,我得到:

file myfile.txt
file.txt: data

所以,我当然试过:

sed -i -t UTF-8 's/\x0A/\x09/g' myfile.txt

但我的 sed 不支持该 -t 选项。

当我尝试这个时:

oc -c myfile.txt

我正在搜索的 [LF] 字符显示为:

\n

我也试过 \0D 作为我的搜索词,也没有运气。

如果有人想通过显示正确的语法向我提供线索,我将不胜感激。

谢谢。

4

5 回答 5

2

谢谢大家,我很感谢那些试图提供帮助的人。如果 StackOverflow 允许我,我会支持每一次提供帮助的尝试。

我正在回答我自己的问题,希望对其他人有所帮助。

我了解到 sed 不能处理 LF 并不完全正确。它可以处理它们,但只有在编写它们时。不是在阅读它们时。

所以,正如我所希望的那样,我不能完全用 sed 完成这项工作。我喜欢 sed 的就地开关,它看起来不像创建另一个文件那么混乱,因此对我的强迫症很有吸引力。

我的文件格式是:

Mary(LF)
Smith(LF)
(SUB)(LF)
John(LF)
Public(LF)
(SUB)(LF)

我想要一个结果:

Mary(TAB)Smith(LF)
John(TAB)Public(LF)

所以,我想把LF改成TAB,把LF-SUB-LF改成LF。

我首先使用 TR 将所有 LF 更改为 TAB,从而解决了我的问题。不能为此使用 sed。

# change LFs to TABs ... so grep can later treat entire file as one line
tr '\012' '\011' < comengo.extract.txt > comengo.extract.out
mv comengo.extract.out comengo.extract.txt

这样,sed 现在可以将整个文件视为一行。sed 只喜欢逐行处理文件,所以我把整行都做得很好。

第二步是让 sed 加入,并进行我想要的更改。我的问题的要点是“我如何表示非打印 ascii 字符?”。

我之前的尝试失败了,因为我试图在 sed 搜索字符串中使用 \x12。现在替换了 LF,我使用了一个不间断的十六进制数字序列。

# changes (tab)(sub)(tab) to just (sub)
sed -i 's/\x09\x1A\x09/\x1A/g'   comengo.extract.tx

然后我使用 sed 将 LFs 恢复到文件中,它可以写 LFs

# (sub) to (tab)(lf)
sed -i 's/\x1A/\x0A\x09/g'  comengo.extract.txt

这就像一个魅力。

于 2013-04-02T01:32:28.270 回答
1

在 sed 中指定换行的可移植方式是使用转义返回:

sed -i 's/\
/<tab>/g'

<tab>用文字制表符替换文本。

于 2013-03-23T02:55:39.010 回答
1

怎么用tr

tr '\012' '\011' < myfile.txt > tmp.out
mv tmp.out myfile.txt

tr命令是一个纯过滤器;它不(在标准版本中,无论如何)采用任何文件名参数或支持覆盖或......

于 2013-03-22T20:37:11.030 回答
1

如果您正在使用bash或者ksh我建议您使用$'...'支持 C 样式反斜杠转义的 shell 语法。例如:

[BASH] # echo $'hello\nworld'
hello
world
[BASH] # echo $'hello\x0aworld'
hello
world
[BASH] #
于 2013-03-24T14:11:54.003 回答
0

事实上 sed 可以匹配 LF 字符,如果您在 --binary 之上使用 --null-data :

$ echo -e "Line1\r\nLine2\rLine3\nLine4\n\rLine5" | sed --null-data --binary -r -e "s/\x0d\x0a/\x0a/g" | od --format=x1a 0000000 4c 69 6e 65 31 0a 4c 69 6e 65 32 0d 4c 69 6e 65 L i n e 1 nl L i n e 2 cr L i n e 0000020 33 0a 4c 69 6e 65 34 0a 0d 4c 69 6e 65 35 0a 3 nl L i n e 4 nl cr L i n e 5 nl

于 2014-09-29T08:38:00.780 回答