我有一堆以下格式的文本文件:
Lorem ipsum dolor sit amet,
consetetur sadipscing elitr,
sed diam nonumy eirmod tempor
invidunt ut labore et dolore
magna aliquyam erat, sed diam
voluptua. - At vero eos et accu-
sam et justo duo dolores et ea
rebum. - Stet clita kasd guber-
gren, no sea takimata sanctus
est Lorem ipsum dolor sit amet.
如何在命令行上将其打印为连续文本,但删除行末尾的音节分隔:
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. - At vero eos et accusam et justo duo dolores et ea rebum. - Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
我可以用来tr '\n' ' '
将换行符转换为空格
问题是tr
只能替换一个字符,我需要一些命令来-\n
提前删除它。如何在 bash 命令行上实现此目的?
答案1
使用awk
:
awk -F'-$' '{ printf "%s", sep $1; sep=/-$/?"":OFS } END{ print "" }' infile
与-F'-$'
,我们定义了F产量S分离器到行末尾的单个连字符,因此通过此操作并采用第一个字段$1
,对于具有该连字符的行,我们将始终拥有没有该连字符的行,对于那些没有该连字符的行,我们将始终拥有整个行。
然后我们只需用 a 打印它sep
之间,但如果当前行以连字符结尾,则读取下一行为空字符串时会发生变化,否则为 OFS (氧输出F产量S分离器,默认为空格字符)。
在END{...}
堵塞我们正在添加最后一个换行符来使其POSIX 文本文件,如果您不想添加它,只需删除该部分即可。
使用sed
,或者:
sed ':loop /-$/N;s/-\n//;t loop; N;s/\n/ /;t loop' infile
- :环形
- 如果一行以连字符结尾(用 测试
/-$/
),请阅读氮ext 行并将“连字符+\n
ewline”替换为空字符串。
如果替换成功(使用 测试t
),则跳转到标签环形并处理下一行并跳过执行其余代码。 - 否则,请阅读氮ext 行并
\n
用空格字符替换这两行之间嵌入的 ewline。
如果这里替换也成功,则跳转到标签环形并处理下一行。
- 如果一行以连字符结尾(用 测试
答案2
另一个perl
解决方案(假设最后一行不以-
字符结尾):
perl -pe 's/-\n//; s/\n/ / if !eof'
sed
与or不同awk
,可以使用 直接操作记录分隔符perl
。所以,如果匹配的话就很容易删除-\n
。s/\n/ / if !eof
然后将用空格替换剩余的换行符,最后一行除外。
如果您不介意末尾有多余的空格,则可以删除该if !eof
部分。
答案3
- 删除行末尾用于连字符的破折号(将连字符的行与过程中的下一行连接起来)。
- 用空格替换换行符。
sed -e ':again' -e '/[[:alpha:]]-$/ { N; s/-\n//; b again; }' file |
paste -s -d ' ' -
这使用sed
连接连字符的行。它通过检测具有破折号且行尾紧接字母的行来实现此目的。通过[[:alpha:]]
在破折号前面进行匹配,我更加确定我只是删除了用于连字符的破折号。然后,通过读入下一行 with N
(插入文字换行符)并删除-\n
.然后重新检查连接的行是否有进一步的连字符(这就是b again
标签分支的作用again
)。
然后使用该paste
实用程序将所有行粘贴到一根连续的行中。该-s
选项用于将所有行连接成一行,并-d ' '
用于指定连接行时使用的分隔符。
我可以使用tr '\n' ' '
它来代替paste
我最终得到的命令,但这会给我一个未终止的行(末尾没有换行符)。
答案4
使用POSIX sed流编辑器实用程序。
sed -e ':a
$!N
s/-\n//;ta
s/\n/ /;ta
' file
和awk实用程序中,我们设置一个循环来读取下一行并操作 ORS 来打印上一行。
awk '
{
while (getline t > 0) {
ORS = sub(/-$/, "") ? "" : OFS
print
$0 = t
}
ORS = RS
}
1' file
$\
我们可以根据当前记录的情况重新排列输出记录分隔符。
perl -lpe '
$\ = eof ? $/
: s/-$// ? $,
: $"
;
' file
$/
是输入记录分隔符,默认为换行符。$"
是引号下的数组元素分隔符,默认为空格。$,
是输出字段分隔符,默认为空字符串。