Bash 使用sed插入换行符(\n)
我正在尝试将一些列表清理到一个正确格式的CSV文件中,以便导入数据库 我的起始文件看起来像这样,每个“行”应该跨越多行,如下所示Bash 使用sed插入换行符(\n),bash,sed,freebsd,Bash,Sed,Freebsd,我正在尝试将一些列表清理到一个正确格式的CSV文件中,以便导入数据库 我的起始文件看起来像这样,每个“行”应该跨越多行,如下所示 Mr. John Doe Exclusively Stuff, 186 Caravelle Drive, Ponte Vedra 33487. 我创建了一个清理文件的sed脚本(有很多“脏”格式,比如双空格和逗号前后的空格)问题在于周期的压缩。我想将该周期更改为新行,但无法使其正常工作 我使用的命令是: sed -E -f scrub.sed test.txt
Mr. John Doe
Exclusively Stuff, 186
Caravelle Drive, Ponte Vedra
33487.
我创建了一个清理文件的sed
脚本(有很多“脏”格式,比如双空格和逗号前后的空格)问题在于周期的压缩。我想将该周期更改为新行,但无法使其正常工作
我使用的命令是:
sed -E -f scrub.sed test.txt
而scrub.sed
脚本如下所示:
:a
N
s|[[:space:]][[:space:]]| |g
s|,[[:space:]]|,|g
s|[[:space:]],|,|g
s|\n| |g
s|[[:space:]]([0-9]{5})\.|,FL,\1\n |g
$!ba
我得到的是
Mr. John Doe,Exclusively Stuff,186 Caravelle Drive,Ponte Vedra,FL,33487n
如果我认为Zip+(句号)是一个很好的使用替换的“分隔符”,那么虽然我可以找到它,但我似乎无法告诉它在那里放一个换行符
我在网上找到的大多数东西都是关于用其他东西替换换行符(通常是删除它们),但用换行符替换的内容并不多。我确实找到了这个,但它不起作用:
我有什么遗漏吗
更新:
我编辑了我的scrub.sed文件,并按照指令添加了文字新行。它仍然不起作用
:a
N
s|[[:space:]][[:space:]]| |g
s|,[[:space:]]|,|g
s|[[:space:]],|,|g
s|\n| |g
s|[[:space:]]([0-9]{5})\.|,FL,\1\
|g
$!ba
我得到的是(一行中的所有内容):
我的预期输出应该是:
Mr. John Doe,Exclusively Stuff,186 Caravelle Drive,Ponte Vedra,FL,33487
Mrs. Jane Smith,Props and Stuff,123 Main Drive,Jacksonville,FL,336907
在sed中获取换行符的可移植方法是反斜杠后跟文字换行符:
$ echo 'foo' | sed 's/foo/foo\
bar/'
foo
bar
我保证使用awk而不是sed可以解决整个问题。BSD上的
sed
不支持新行的\n
表示(将其转换为文本n
):
GNUsed
不支持\n
表示:
$ echo "123." | gsed -E 's/([[:digit:]]*)\./\1\nnext line/'
123
next line
备选方案包括:
使用单个字符分隔符,然后使用tr
转换为新行:
$ echo "123." | sed -E 's/([[:digit:]]*)\./\1|next line/' | tr '|' '\n'
123
next line
或者在sed脚本中使用转义文字新行:
$ echo "123." | sed -E 's/([[:digit:]]*)\./\1\
next line/'
123
next line
或定义新行:
$ echo "123." | sed -E 's/([[:digit:]]*)\./\1|next line/' | tr '|' '\n'
123
next line
POSIX:
nl='
'
BASH/zsh/其他支持:
然后使用带有适当引号和转义符的sed
插入文字\n
:
echo "123." | sed 's/\./'"\\${nl}"'next line/'
123
next line
或者使用awk
:
$ echo "123." | awk '/^[[:digit:]]+\./{sub(/\./,"\nnext line")} 1'
123
next line
或者使用GNU-sed,它支持Oracle Linux x8664上的以下工作:
$ echo 'foobar' | sed 's/foo/foo\n/'
foo
bar
如果需要每行匹配一次以上,则需要在末尾放置一个g
,如所示:
$ echo 'foobarfoobaz' | sed 's/foo/foo\n/g'
foo
barfoo
baz
在比赛后添加一行。 sed命令可以在找到模式匹配后添加新行。sed的“a”命令告诉它在找到匹配项后添加新行 sed'/unix/a“添加新行”file.txt 在匹配前添加一行 sed命令可以在找到模式匹配之前添加新行。sed的“i”命令告诉它在找到匹配项之前添加新行 sed'/unix/i“添加新行”'file.txt
这里似乎很好用。使用相同的文件和脚本,我在最后用换行符重新格式化了数据。将
\n\n
放在sed脚本的倒数第二行中,可以得到预期的两行换行符。(然而,我在“Doe”和“exclusive”之间没有逗号)。我在Linux上使用(GNU sed)4.4。您使用的是哪个版本/平台?我知道了,我正在FreeBSDAh上使用sed
。如果可以的话,可以尝试使用GNU sed?我还看到,我在输出中得到了“FL”,正如您希望从脚本中得到的一样。你确定你提供的输出来自你提供的脚本吗?这是正确的。在试图混淆真实数据时,我无意中删除了FL。考虑不要在邮政编码之后删除换行符。将s |\n | | g
更改为s |\([^[:space:]\)\n\([^[:space:]\)\124;\ 1\2 | g
,以便只转换后面带有字符的新行。然后,您不必恢复您没有删除的内容。我正试图在sed脚本中使用转义文字,如图所示,但由于任何原因,它不起作用。但是,re:关于您所说的BSD不支持\n
,我将改变策略,将tr
合并到BSD中。我从未想到它不受支持。谢谢我正试图在sed脚本中使用转义文字,如图所示,但无论出于何种原因,它都不起作用。在一个sed
脚本和一行sed
脚本中很难做到这一点。您还可以使用多字符分隔符(例如
),然后使用awk
将其更改为\n
。老实说,POSIXsed
最好只用于单行更改。在脚本中添加文字换行并不比在命令行上难-语法不会更改。显然,您永远不会真正插入一个字符或字符串,然后通过管道将其转换为换行符,因为这是不必要的脆弱和低效的。不过,OPs剩下的问题与此无关,对于他提出的问题来说效果很好,而他现在的问题是他的脚本的另一部分(他的循环中的s|,[[:space:]]|,| g
在添加新行后删除它)。@EdMorton:我想我没有尝试用字面上的新行调试他的脚本。我确实记得(作为一个BSD用户)让我挠头的时候,我觉得它应该工作,但没有。是的,Solaris sed更糟糕。如果它不是简单的s/old/new/
,那么你就陷入了混乱符文的不同组合中,包括每一个标点符号、单个字母和蝙蝠侠符号,每一个符号的含义都在一个接一个地变化。因此,awk…:-)。lol-unix是众所周知的非开源
$ echo 'foobar' | sed 's/foo/foo\n/'
foo
bar
$ echo 'foobarfoobaz' | sed 's/foo/foo\n/g'
foo
barfoo
baz
unix is great os. unix is opensource. unix is free os.
"Add a new line"
learn operating system.
unixlinux which one you choose.
"Add a new line"
"Add a new line"
unix is great os. unix is opensource. unix is free os.
learn operating system.
"Add a new line"
unixlinux which one you choose.