1

对整个 Unix 来说非常新。我目前正在使用 korn shell 来尝试格式化一些文本行。

我的输入有几行看起来像这样

Date/Time        :- Monday June 03 00:00:00 EDT 2013
Host Name        :- HostNameHere
PIDS             :- NumbersNLetters
Product Name     :- ProductName

所需的输出如下:

Date/Time="Monday June 03 00:00:00 EDT 2013" HostName="HostNameHere" PIDS="NumbersNLetters" ProductName="ProductName"

所以,我需要去掉最左边一列中的任何空格,并将最右边一列中的所有内容都放在引号之间。我已经查看了 cut 命令,并且做到了这一点:

Cut -f 1,2 -d -

这可能会产生类似的结果Date/Time:Monday June 03 00:00:00 EDT 2013,这与我想要的很接近,但不完全是。我不确定 cut 是否可以让我添加括号,而且看起来我也不能以这种方式删除空格。

sed似乎它可能更接近答案,但我无法通过谷歌搜索找到我如何寻找任何模式而不是特定模式。对于这个令人难以置信的基本问题,我深表歉意,但阅读文档只能在你的大脑开始疼痛之前让你走这么远......如果有更好的资源我应该看一下,我很乐意指出正确的方向。谢谢!

4

6 回答 6

4

Perl 也是 :)

perl -0777 -pe 's/ +(?=.*:-)//g;s/^(.*?):-\s*(.*)\s*/$1="$2" /gm' < file.txt

从@Endoro 的输入产生:

Date/Time="Monday June 03 00:00:00 EDT 2013" HostName="HostNameHere" PIDS="NumbersNLetters" ProductName="ProductName" Date/Time="Monday June 03 00:00:00 EDT 2013" HostName="HostNameHere" PIDS="NumbersNLetters" ProductName="ProductName" Date/Time="Monday June 03 00:00:00 EDT 2013" HostName="HostNameHere" PIDS="NumbersNLetters" ProductName="ProductName" Date/Time="Monday June 03 00:00:00 EDT 2013" HostName="HostNameHere" PIDS="NumbersNLetters" ProductName="ProductName" 

或者如果你想要一个\n到最后

perl -0777 -nE 's/ +(?=.*:-)//g;s/^(.*?):-\s*(.*)\s*/$1="$2" /gm;say' < file.txt
于 2013-06-28T23:46:06.017 回答
3

代码仅适用于 GNU sed:

sed -nr 's/(.*)\b\s+:-\s(.*)/\1="\2" /;H;s/.*//;${x;:k;s/\n(.*)\n(.*)/\1\2/g;tk;p}' file

..输出示例:

$猫文件
日期/时间:- 2013 年 6 月 3 日星期一 00:00:00 EDT
主机名:- HostNameHere
PIDS :- NumbersNLetters
产品名称:- 产品名称
日期/时间:- 2013 年 6 月 3 日星期一 00:00:00 EDT
主机名:- HostNameHere
PIDS :- NumbersNLetters
产品名称:- 产品名称
日期/时间:- 2013 年 6 月 3 日星期一 00:00:00 EDT
主机名:- HostNameHere
PIDS :- NumbersNLetters
产品名称:- 产品名称
日期/时间:- 2013 年 6 月 3 日星期一 00:00:00 EDT
主机名:- HostNameHere
PIDS :- NumbersNLetters
产品名称:- 产品名称

$sed -nr "s/(.*)\b\s+:-\s(.*)/\1=\"\2\" /;H;s/.*//;${x;:k ;s/\n(.*)\n(.*)/\1\2/g;tk;p}" 文件
Date/Time="Monday June 03 00:00:00 EDT 2013" Host Name="HostNameHere" PIDS="NumbersNLetters" Product Name="ProductName" Date/Time="Monday June 03 00:00:00 EDT 2013" Host Name="HostNameHere" PIDS="NumbersNLetters" Product Name="ProductName" Date/Time="Monday June 03 00:00:00 EDT 2013" Host Name="HostNameHere" PIDS="NumbersNLetters" Product Name="ProductName" Date /Time="2013 年 6 月 3 日星期一 00:00:00 EDT" 主机名="HostNameHere" PIDS="NumbersNLetters" 产品名称="ProductName"

在某些环境中,"双引号"必须用反斜杠转义。

于 2013-06-28T22:05:59.013 回答
3

一种方法awk

awk '{
    gsub(/[[:space:]]+/,"",$1);
    gsub(/.*/,"\"&\"",$2);
    print $1,$2
}
END { print "\n" }' FS=':- ' OFS='\=' ORS=' ' inputFile

单线

awk '{gsub(/ /,"",$1);print $1,q$2q}END{print "\n"}' OFS='\=' q='"' FS=' +:- ' ORS=' ' file
于 2013-06-28T21:57:49.060 回答
2

这可能对您有用(GNU sed):

sed -r ':a;s/ (\S*:-.*)$/\1/;ta;s/:-\s*/="/;s/$/"/;1h;1!H;$!d;x;s/\n/ /g' file
  • :a;s/ (\S*:-.*)$/\1/;ta删除剩下的任何空格:-
  • s/:-\s*/="/替换:-="
  • s/$/"/"在行尾插入 a 。
  • 1h;1!H对于第一行,将模式空间 (PS) 插入保持空间 (HS)。之后将 PS 附加到 HS。
  • $!d除最后一行之外的所有内容都删除 PS 并将下一行读入 PS。
  • x在最后一行将 HS 换成 PS
  • s/\n/ /g用空格替换所有换行符并打印出结果一行。
于 2013-06-29T18:31:49.820 回答
2

基本上,您想对输入应用三种不同的转换:

  1. 在每一行上,删除:-.
  2. 在每一行上,将:-后跟空格替换为=".
  3. 在每一行上,添加"到末尾。
  4. 用空格替换换行符。

在尝试提出正确的命令之前创建这样的计划总是一个好主意。

要执行第一步,使用sed将是最好的选择。sed适用于正则表达式,您可以在Regular-Expressions.info上阅读。因为我们只想在表达式需要了解其周围环境之前删除空格。:-为此,可以使用零宽度的lookbehnd 断言来检查模式(空格,用 表示\s)是否不会替换:-一行之后的任何内容。但是sed不支持正则表达式的这一特性,我们将使用 perl 单行器来代替。

perl -pe 's/\s*(?=.*:-)//g'

这意味着:用:-空字符串替换任意数量的字符之后的任何空格。g代表全局并导致模式替换所有匹配项,而不仅仅是第一个匹配项。使用perl -pein 与使用相同sed但允许更高级的正则表达式。

第二步稍微简单一点:用 . 替换:-加任何空格=

sed 's/:-\s*/="/'

第三步超级简单:

sed 's/$/"/'

在这里,$表示行尾。顺便说一句,sed可以将两个或多个命令组合为一个使用;分隔符:

sed 's/:-\s*/="/;s/$/"/'

这会稍微快一点。我可以告诉你也使用sed最后一步,但我会借此机会向你展示另一个核心命令:tr. trtranslate的缩写,将任何单个字符替换为另一个字符。它比 sed 快得多。

tr '\n' ' '

在这里,\n代表换行符(ASCII 码0x0a)。

因此,将所有部分放在一起:

cat input | perl -pe 's/\s*(?=.*:-)//g' | sed 's/:-\s*/="/;s/$/"/' | tr '\n' ' '

为了进一步研究,您可能需要阅读 和 的手册sedtr。为此,请输入以下命令:

man sed
man tr
于 2013-06-28T22:08:49.577 回答
2

你可以做这样的事情让你开始

awk '{
  if (NR % 4)
printf("%s ", $0)
  else
printf("%s\n", $0)
}' file

在这里找到http://www.unix.com/shell-programming-scripting/115070-how-can-i-join-three-lines-into-one-unix.html

然后使用剪切

于 2013-06-28T21:34:19.910 回答