我有如下文件的txt文件。
abc
def
ghi
123
456
789
预期产出
abc|def|ghi
123|456|789
我想用管道符号(|)替换新行。我想在egrep.After空行后使用它应该开始其他新行。
答案 0 :(得分:6)
您可以尝试使用awk
awk -v RS= -v OFS="|" '{$1=$1}1' file
你明白了,
abc|def|ghi
123|456|789
<强>解释强>
将RS
设置为空/空值以使awk对空行序列进行操作。
来自POSIX specification for awk:
<强> RS 强>
RS的字符串值的第一个字符应为输入记录分隔符;一个默认情况下。如果RS包含多个字符,则结果未指定。 如果RS为空,则记录由包含一个或多个空行的序列分隔,前导或尾随空白行不应在输入的开头或结尾处产生空记录,并且a应始终为字段分隔符,无论FS的值是什么。
$1==$1
使用OFS重新格式化输出作为分隔符,1
为true
以便始终打印。
答案 1 :(得分:2)
这是使用GNU sed
:
cat file | sed ':a; N; $!ba; s/\n/|/g; s/||/\n/g'
如果您正在使用BSD sed
(Mac OS X打包的风格),则需要单独传递每个表达式,并使用文字换行符而不是\n
({ {3}}):
cat file | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/|/g' -e 's/||/\
/g'
如果file
是:
abc
def
ghi
123
456
789
你得到:
abc|def|ghi
123|456|789
这会将每个换行符替换为|
(归功于more info),然后使用换行符替换||
(即原始输入中的一对换行符)。
这里需要注意的是|
不能出现在输入行的开头或结尾;否则,第二个sed
会在错误的位置添加换行符。要解决此问题,您可以使用另一个不会在输入中作为中间值的字符,然后将该字符的单例替换为|
并与\n
配对。
这是一个实现上述解决方法的示例,使用NUL字符\x00
(应该很可能不会出现在您的输入中)作为中间字符:
cat file | sed ':a;N;$!ba; s/\n/\x00/g; s/\x00\x00/\n/g; s/\x00/|/g'
说明:
:a;N;$!ba;
将整个文件放在模式空间中,包括换行符s/\n/\x00/g;
用NUL字符替换所有换行符s/\x00\x00/\n/g;
用换行符替换所有NUL对s/\x00/|/g
用|
BSD版本:
sed -e ':a' -e 'N' -e '$!ba' -e 's/\n/\x00/g' -e 's/\x00\x00/\
/g' -e 's/\x00/|/g'
对于更直接的方法(仅限GNU sed
),由@ClaudiuGeorgiu提供:
sed -z 's/\([^\n]\)\n\([^\n]\)/\1|\2/g; s/\n\n/\n/g'
说明:
-z
使用NUL字符作为行尾(因此新行不会得到特殊处理,并且可以在正则表达式中匹配)s/\([^\n]\)\n\([^\n]\)/\1|\2/g;
将<non-newline><newline><non-newline>
的每个3个字符的序列替换为<non-newline>|<non-newline>
s/\n\n/\n/g
用一个换行符替换所有换行符答案 2 :(得分:1)
在原生bash中:
#!/usr/bin/env bash
curr=
while IFS= read -r line; do
if [[ $line ]]; then
curr+="|$line"
else
printf '%s\n' "${curr#|}"
curr=
fi
done
[[ $curr ]] && printf '%s\n' "${curr#|}"
测试:
$ f() { local curr= line; while IFS= read -r line; do if [[ $line ]]; then curr+="|$line"; else printf '%s\n' "${curr#|}"; curr=; fi; done; [[ $curr ]] && printf '%s\n' "${curr#|}"; }
$ f < <(printf '%s\n' 'abc' 'def' 'ghi' '' 123 456 789)
abc|def|ghi
123|456|789
答案 3 :(得分:1)
使用rs。例如:
rs -C'|' 2 3 < file
rs =重塑数据数组。在这里,我指定我想要2行,3列,并且输出分隔符是管道。