通过bash/awk/sed/perl去除特定文本后的换行符

17

我想删除一个特定字符串后面出现的所有换行符,并用制表符替换它们。比如说,我的 sample.txt 文件内容如下:

foo
bar bar bar bar some text

我希望它如此

foo    bar bar bar bar some text

我该如何通过bash/awk/sed实现这个操作。帮帮我。


1
“some text” 发生了什么? - Michael J. Barber
刚错过了,我想这没什么区别。所以期望的输出应该是:foo bar bar bar bar 一些文本 - Greenhorn
10个回答

21
在awk中:
awk '/foo$/ { printf("%s\t", $0); next } 1'

太棒了!很快就完成了。谢谢 :) - Greenhorn
是的,那是一种典型的awk方法。我在答案中写了一个sed解决方案... :) - DejanLekic
4
对于那些想知道末尾为1的原因的人,简单来说,它将翻译为“{print $0}”,这样不匹配foo的行将按原样打印,即基本格式为“awk '{/some_pat/{/* if pat is true /} {/ if pat is false */}'”。 - Sanjay T. Sharma

9

2
你不需要使用 cat。你可以直接将文件名传递给 sed - Luis Lavaire.

5
perl -pe 's/(?<=foo)\n/\t/' input

4
这可能适合您使用:

这可能适合您:

echo -e "foo\nbar bar bar bar some text"| sed '/foo$/{N;s/\n/\t/}'
foo     bar bar bar bar some text

实际上:

echo -e "foo\nbar bar bar bar some text"| sed '/foo$/N;s/\n/\t/'
foo     bar bar bar bar some text

后一种解决方案的效率略低,但差别不大!

4
“sed”版本看起来像这样:
#!/bin/sed -f
/foo/{
N
s/\n/\t/
}

如果这就是您在sed命令中想要做的全部内容,您可以将上述内容简化为一行代码:
sed -e '/foo/N;y/\n/\t/'  <sample.txt

解释: N 添加一个换行符和下一行的输入;y/\n/\t 将所有换行符替换为制表符,或者 s/\n/\t/ 将第一个换行符替换为制表符。

请注意,由于 sed 是面向行的,输入中的换行符被视为行分隔符而不是行的一部分(这与 Perl 不同)。


3
perl -pe 's/foo\n/foo\t/g' temp2.txt

以下是测试内容。

243> cat temp2.txt 
foo
bar bar bar bar some text 
pearl[ncm_o12.2_int_x86.@2].244> perl -pe 's/foo\n/foo\t/g' temp2.txt
foo     bar bar bar bar some text 

2

并非所有工具都能进行换行符替换。Perl可以:

cat file.txt | perl -p -e 's/\n/ /g'

5
  1. 你漏掉了“foo”的要求。
  2. 你漏掉了“tab”(制表符)的要求。
- sehe

2

嗯,不确定这是否符合您的要求,但我会在vim中完成这个操作:

:g/^foo$/join

或者,如果 foo 可能出现在一行的任何位置:

:g/foo$/join

当然,:%s/foo\n/foo\t/g 也可以很好地完成这个任务。

也尝试了这个!成功了 :) - Greenhorn

0

我找不到一个纯Bash的例子,实际上这是一个符合POSIX标准的Bourne shell示例,这是它:

#!/bin/bash

while read line 
do  
case "$line" in     

  foo )        printf "${line}\t";      
                ;;      
     * )        printf "${line}\n";   
esac 
done <file.txt

这是一个while循环,对于read程序读取的每一行,都将该行存储在名为line的变量中(我们将其称为"${line}"),do启动循环中的工作。我们使用case检查该行是否等于foo,如果是,则使用printf打印该行后跟一个(printf不会打印换行符,除非您指示它这样做),我们指定;;,以便它继续执行(它不会尝试另一个匹配,*也将匹配foo并再次打印foo后跟一个换行符,因此,对于所有其他不匹配foo的行,我们使用printf打印带有换行符结尾的行。esac结束了case语句。done结束了while循环,<file.txt指令将文件file.txt发送到read的标准输入(stdin)进行处理。

0

如果你确定你的字符串不包含回车符(\r),你可以这样做:

echo "$string" | tr '\n' '\r' | sed 's/foo\r/foo\t/g' | tr '\r' '\n'

步骤:
  • tr 将所有换行符 (\n) 替换为回车符 (\r)
  • sed 将所有字符串 foo\r 的出现替换为 foo\t
  • 最后的 tr 反转了换行符 / 回车符的替换。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接