20140918-17:31:19.835
34=11
52=20140918-17:31:19.812
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
20140918-17:31:19.837
34=12
52=20140918-17:31:19.813
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
20140918-17:31:19.838
34=13
52=20140918-17:31:19.813
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
我有这个输入,想要像这样格式化:
34=11 20140918-17:31:19.835
52=20140918-17:31:19.812
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
34=12 20140918-17:31:19.837
52=20140918-17:31:19.813
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
34=13 20140918-17:31:19.838
52=20140918-17:31:19.813
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
我没有shell脚本编写经验,我担心这个问题可能不合适,但是如果你能指出一个很好的shell脚本教程可以让我开始,我会很感激!
答案 0 :(得分:4)
您可以使用awk
:
awk '!/=/{m=$0; next}m{$0=$0 FS m; m=0}/^52=/{$0="\t"$0}/^273=/{$0="\t\t"$0}1' file
!/=/{m=$0; next}
- 如果该行不包含=
,则行记录($0
)将分配给m
变量。 next
跳到下一行,因为无需进一步处理。
m{$0=$0 FS m; m=0}
- 如果定义了m
(大于零),请将当前行($0
)附加到字段分隔符(FS
)和变量m
(上一行)。最后,将m
变量重置为零,因为我们需要确保此代码块在不包含=
字符的行之后立即执行。
/^52=/{$0="\t"$0}
- 如果当前行以52=
开头,则在当前行记录($0
)前加上制表符(\t
)
/^273=/{$0="\t\t"$0}
- 如果当前行以273=
开头,请在当前行记录前加上两个制表符。
1
- 无论条件如何,这只是一句简短的说法{print}
。 1
只是告诉awk
print是真的。如果条件为真且没有提供下面的代码块,则awk
的默认操作就是打印,你可以用任何真实的东西替换它。
在任何UNIX系统上,awk
都是用于处理文本文件的语言。
我发现this intro非常简洁。此外,awk.info有大量的概述和教程。就文档而言,GNU Awk User's Guide非常全面。
答案 1 :(得分:2)
以下是使用sed
sed -r '
/^2014/ { # For lines starting with 2014
N; # Append next line to pattern space
s/^([^\n]+)\n([^\n]+)/\2 \1/; # Merge the first line with second
}
/^52/ { # For lines starting with 52
s/^/\t/ # Add a tab in the front of the line
}
/^273/ { # For lines starting with 273
s/^/\t\t/ # Add a tab in the front of the line
}' file
34=11 20140918-17:31:19.835
52=20140918-17:31:19.812
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
34=12 20140918-17:31:19.837
52=20140918-17:31:19.813
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
34=13 20140918-17:31:19.838
52=20140918-17:31:19.813
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
273=17:31:19.797
作为一个单行:
sed -r '/^2014/N;s/^([^\n]+)\n([^\n]+)/\2 \1/;/^52/s/^/\t/;/^273/s/^/\t\t/' file
答案 2 :(得分:0)
AWK与Jaypal一样出色,约翰用解决方案描述。在您是新手时,您可以通过运行基本的Unix / Linux级别命令来执行相同的操作,并且通过查看其手册页,它将帮助您了解这些命令正在执行的操作。
请注意,以下解决方案不是像John / JayPal所提供的那样有效的解决方案,但会让您完全了解我的意思以及您的输出请求。
假设您的文件名是1.txt“,其中包含数据,请运行以下 runme.sh
#!/bin/bash
grep "^[0-9][0-9]=[0-9][0-9]$" 1.txt > 2-2.txt
grep "^[0-9][0-9][0-9][0-9]*.*-[0-9][0-9]*\:[0-9][0-9]*.*\.[0-9][0-9]*$" 1.txt > datetime.txt
grep "^[0-9][0-9]=.*-[0-9][0-9]*\:[0-9][0-9]*.*\.[0-9][0-9]*$" 1.txt > equal_datetime.txt
grep "^[0-9][0-9][0-9]=.*[0-9]$" 1.txt > 3_eq_lines.txt
paste 2-2.txt datetime.txt equal_datetime.txt > headers.txt
c=1; while read line1 line2 line3; do echo -e "$line1 $line2\n $line3"; echo -e "`tail -n +$c 3_eq_lines.txt | head -4|sed "s/^/ /"`"; ((c+=3)); done < headers.txt
rm 2-2.txt datetime.txt equal_datetime.txt 3_eq_lines.txt headers.txt
答案 3 :(得分:0)
也许是perl
perl -lnE '$l1=$_,next unless m/=/; #store the line without =
s/$/ $l1/ if m/^\d\d=\d\d$/; #merge this line with the stored
s/^/\t/ if m/^\d+=\d{8}/; #if the = is followed by 8 digits -> 1xtab
s/^/\t\t/ if m/^\d+=\d\d:/; #if the = is followed by 2digits and : -> 2xtab
print $_;' filename