在linux中的文件中加入行

时间:2015-09-21 12:34:17

标签: linux bash awk sed

我已经向以下方面发出了答复......请找到它。如果您可以,请随意优化它。)。

所以问题的简要描述:我已经创建了一个带有来自psql查询的大量输出的文件,我试图使用这些数据,但输出的格式并不理想。以下是数据的细分:

  

some_date | some_username | some_port | 声明:

     

:选择some_query

     

some_date | some_username | some_port |声明:SELECT some_different_query

这就是数据的样子,问题是粗线。我不知道为什么这句话被分成两行,但它与我需要做的其余处理相混淆。如果我只看粗体部分的字符,它的含义如下:

  

声明产品:> $

     

产品:>查询$

>是空格,$是eol字符。

所以我真的需要将这两行加在一起,但我不知道如何。这是我到目前为止所尝试的:

sed 's/\n://g' filename
显然,这不起作用。也有道理,因为我相信SED在线到线的基础上工作。任何建议都将很高兴。

以下是数据的屏幕截图。我无法复制数据,因为我的VM无法允许它。遗憾...

enter image description here

以下是我希望看到这些数据的方式...尝试使用你的awk:P:

enter image description here

4 个答案:

答案 0 :(得分:2)

sed用于单个行上的简单替换,即全部。对于任何更有趣的事情,你应该使用awk来实现清晰,简洁,健壮,可移植性以及几乎所有其他理想的软件属性。

鉴于我编写的这个示例输入文件:

$ cat file
some_date | some_username | some_port | statement:
: SELECT some_query
:lines and lines
:of stuff...
some_date | some_username | some_port | statement: SELECT some_different_query
some_date | some_username | some_port | statement:
: SELECT something else where
:the quick brown fox
: jumped over
: the lazy
:dog's back

这个awk命令可能就是你想要的:

$ awk '{printf "%s%s", (NR==1 || sub(/^: */,OFS) ? "" : ORS), $0} END{print ""}' file
some_date | some_username | some_port | statement: SELECT some_query lines and lines of stuff...
some_date | some_username | some_port | statement: SELECT some_different_query
some_date | some_username | some_port | statement: SELECT something else where the quick brown fox jumped over the lazy dog's back

但是我必须自己编写输入集以进行测试,因此它可能与您的实际输入不匹配,而且您没有发布任何预期的输出,所以我只是猜测。

如果没有,请编辑您的问题,以提供几行具体,可测试的样本输入和预期输出。

如果您不熟悉awk和其他类C语言,请参阅awk命令的含义:

awk '
  {                      # WHILE read the current line ($0) DO
  printf "%s%s",         #   prepare to print 2 strings with no trailing newline
  (NR==1                 #   IF this is the first line of input
  || sub(/^: */,OFS)     #     OR we can replace :<space>* with one space (OFS)
  ?                      #   THEN
  ""                     #     the first string to print is NULL
  :                      #   ELSE
  ORS                    #     the first string to print is a newline (ORS)
  )                      #   ENDIF
  , $0                   #   the second string to print is the current input line
  }                      # ENDWHILE
  END{print ""}          # print a newline (ORS) at the end of the output
' file

该部分被注释为IF..ENDIF只是许多语言中使用的常见三元表达式,OFS和ORS是awk内置变量而不是包含输出字段分隔符和输出记录分隔符字符串(默认情况下是单个空格和换行符。)

答案 1 :(得分:1)

sed -e ':a' -e '/: $/{s///;N;s/\n: //;ba' -e '}' YourFile

尝试重新组合以切割分隔符结尾的行(并将其删除)

N将新行加载到当前缓冲区,因此您可以使用多行并将换行视为普通字符

使用新信息,其中有1行以:结尾,后面跟着说明 `:\但不以先前的分隔符结尾

sed -e 's/: $//;1h;1!H;$!d' -e 'x;s/\n: //g' YourFile

答案 2 :(得分:0)

所以它不漂亮,但我找到了答案:)。可能有一些方法可以缩短这条线,我很欣赏任何关于如何做的回应,我喜欢学习新的做事方式。这就是答案:

sed ':x; /\:$/ { N; s/\:\n//; tx }' temp.txt | sed ':x; /\, $/ { N; s/\n\://; tx }' | sed ':x; /.\([a-zA-Z0-9]*\)$/ { N; s/\n\://; tx }'

希望我没有复制错误。一个简短的解释,适用于任何想要使用类似实例的人。第一部分查找以:结尾的所有行,并替换换行符和下一行的第一个:。第二部分查找以,结尾的所有行,并替换那里的换行符和下一行的:。最后一部分查找以任何正常字符或数字结尾的所有行(因此[a-zA-Z0-9])并删除换行符以及下一行的:

复杂(对我来说至少:)),但很有趣。

感谢所有回复。

已编辑2015-09-22

我设法将这个可怕的长期命令发送到一个'更简单'的一个班轮:

sed -e ':loop' -e ':x; /.\([a-zA-Z0-9]*\)$/ { N; s/\n\://; tx }' -e 'b loop'

适用于我迄今为止发现的每一个案例:)。我标记为答案的awk答案仍然是最简单的。

-Ryan

答案 3 :(得分:0)

这可能适合你(GNU sed):

sed 'N;s/:\n:/:/;P;D' file

或者如果该行被分成多行:

sed ':a;N;s/:\n:/:/;ta;P;D' file