我的查询中有下表,+
但我的分隔符是在“描述”下创建新行,如下例所示:
TYPE+DESCRIPTION+PRIORITY+DATE
1+text1+HIGH+Aug 15
+text2
2+text+LOW+Aug 11
3+text+LOW+Aug 11
4+text1+HIGH+Aug 15
+text2
+text3
我如何使用 sed 让它看起来像下面这样
TYPE DESCRIPTION PRIORITY DATE
1 text1 text2 HIGH Aug 15
2 text LOW Aug 11
3 text LOW Aug 11
4 text text2 text3 HIGH Aug 15
我努力了:
sed -n '1{h;n};/^ *+ */{s// /;H;n};{x;s/\n//g;p};${x;p}'
但给了我错误(sed:命令乱码),谢谢
答案1
awk '
BEGIN{OFS=FS="+"}
{sub(/[[:blank:]]+$/,"")} #Removes trailing blanks
NF==4{print line;line=$0}
NF==2{x=$2;$0=line;$2=$2" "x;line=$0}
END{print line}
' file | column -ts "+"
其背后的主要思想是 if NF==2
, then 将第二个字段放入$2
前一行的第二个字段中。所以发生的事情是
1+text1+HIGH+Aug 15 #Puts this in "line" variable
+text2 #Transfer 2nd field to "line" second field
# Resulting in...
1+text1 text2+High+Aug 15
column
+
从输出中删除来生成这个精细的最终输出:
TYPE DESCRIPTION PRIORITY DATE
1 text1 text2 HIGH Aug 15
2 text LOW Aug 11
3 text LOW Aug 11
4 text1 text2 text3 HIGH Aug 15
答案2
打造“领域不可知论”awk
tac file | awk 'BEGIN{FS="+"}
{flds=(NF>flds)?NF:flds;for (i=1; i<=NF; i++) {f=(length($i)>0)?gensub(/ +$/,"","g",$i)" ":"";fld[i]=f fld[i]}}
$1>0{for (i=1; i<=flds; i++) printf fld[i]"+"; printf "\n"; delete fld}' |
tac | column -ts "+"
TYPE DESCRIPTION PRIORITY DATE
1 text1 text2 HIGH Aug 15
2 text LOW Aug 11
3 text LOW Aug 11
4 text1 text2 text3 HIGH Aug 15
演练
翻转文件,以便当 $1 不为空并设置时就知道是时候打印了FS
tac file | awk 'BEGIN{FS="+"}
计算最大数量flds
,循环遍历字段,修剪它们并检查空白,按字段将它们加载到数组中以聚合它们
{flds=(NF>flds)?NF:flds;for (i=1; i<=NF; i++) {f=(length($i)>0)?gensub(/ +$/,"","g",$i)" ":"";fld[i]=f fld[i]}}
如果$1
非空则输出该行并重置数组
$1>0{for (i=1; i<=flds; i++) printf fld[i]"+"; printf "\n"; delete fld}' |
通过管道tac
将其翻转并用于column
美化它
tac | column -ts "+"
编辑
真的不喜欢第二个循环,gensub
当你可以sed
在管道中用锤子敲击它时停止到每个字段,并且可以简化测试。感觉不优雅。
所以这里有一个打高尔夫球版本只是感觉对我更好:
tac file | awk 'BEGIN{FS="+"}
{flds=(NF>flds)?NF:flds;
for (i=1; i<=NF; i++) {fld[i]=$i" "fld[i];
if ($1) printf fld[i]"+"}}
$1{ printf "\n"; delete fld}' |
sed -E "s/ +/ /g" | tac | column -ts "+"
答案3
返回并阅读我们的 sed 版本之间可能存在的差异,并从头开始重写它。希望这有效:
:r
$!N
y:+:,:
/\n,/{
s:^\([^,]\{1,\},[^,]\{1,\}\)\([^\n]\{1,\}\)\n,\([^ \n]\{1,\}\).*$:\1 \3\2:
br
}
$!P
$!D
输出:
TYPE,DESCRIPTION,PRIORITY,DATE
1,text1 text2,HIGH,Aug 15
2,text,LOW,Aug 11
3,text,LOW,Aug 11
4,text1 text2 text3,HIGH,Aug 15
答案4
perl -0pe 'while(s/(.*?)\+(.*?)\+(.*)\n\+(.*)/$1+$2 $4+$3/g){}' file
perl -0
- 吞掉所有输入s/(.*?)\+(.*?)\+(.*)\n\+(.*)/$1+$2 $4+$3/g
A+B+...C\n+D
在可能的情况下进行转变A+B D+...C
。