我有一个空格分隔的文件,我需要将其转换为管道分隔但是当它遇到每行中的特定模式时,它需要在执行sed时排除这些模式。
a char(30) NOT NULL
b LARGEINT NOT NULL
c TIMESTAMP
d numeric(10, 3)
预期输出
a|char(30)|NOT NULL
b|LARGEINT|NOT NULL
c|TIMESTAMP|
d|numeric(10, 3)|
在替换空格时,需要忽略(10,3)中的空格和NOT NULL。 我试过以下但是没有用
sed -ri '|, |!s|\ /\|/g' abc.txt
对此方面的任何帮助表示赞赏。
答案 0 :(得分:3)
在GNU awk中使用FPAT
:
$ awk '
BEGIN {
FPAT="([^ ]+)|([^ ]*NOT NULL[^ ]*)|([^ ]*numeric([^)]*)[^ ]*)" # set FPAT
OFS="|" # set OFS
}
{ NF=3; $1=$1 } # rebuild record (1)
1' file # and output
a|char(30)|NOT NULL
b|LARGEINT|NOT NULL
c|TIMESTAMP|
d|numeric(10, 3)|
(1)NF=3
将字段计数静态设置为3,并导致c和d记录末尾的管道。
答案 1 :(得分:1)
它不是特别漂亮,但两个表达式 sed
表达式可以正常工作,
$ sed -e 's/\([^,T]\)[ ]/\1\|/g' file.txt | sed -e 's/\([^O]T\)[ ]/\1\|/'
a|char(30)|NOT NULL
b|LARGEINT|NOT NULL
c|TIMESTAMP
d|numeric(10, 3)
如果你真的想在TIMESTAMP
和)
之后使用管道,你可以在末尾添加第三个,例如
$ sed -e 's/\([^,T]\)[ ]/\1\|/g' file.txt | sed -e 's/\([^O]T\)[ ]/\1\|/' \
-e 's/\([^L]\)$/\1\|/'
a|char(30)|NOT NULL
b|LARGEINT|NOT NULL
c|TIMESTAMP|
d|numeric(10, 3)|
但是我把最后的管道作为我的输入文件中没有空格的尾随空格。无论哪种方式,它都是皮肤这种猫的另一种方式。
答案 2 :(得分:1)
如果我理解正确的话,这些是要求:
|
为分隔符()
中可能包含空格以下将适用于给定的样本
$ cat ip.txt
a char(30) NOT NULL
b LARGEINT NOT NULL
c TIMESTAMP
d numeric(10, 3)
$ sed -E 's/ +/|/; s/\) */)|/; /\)/!s/ +|$/|/' ip.txt
a|char(30)|NOT NULL
b|LARGEINT|NOT NULL
c|TIMESTAMP|
d|numeric(10, 3)|
s/ +/|/
将第一次出现的一个或多个空格更改为|
s/\) */)|/
首先处理麻烦的第二场。将)
和可选空格更改为)|
()
/\)/!s/ +|$/|/
,如果不包含)
,则将第一次出现的一个或多个空格或行尾更改为|
答案 3 :(得分:0)
awk '/^[cd]/{$NF=$NF"|"}{sub(/ /,"|")sub(/ N/,"|N")}1' file
a|char(30)|NOT NULL
b|LARGEINT|NOT NULL
c|TIMESTAMP|
d|numeric(10, 3)|
会发生什么? 首先是在以c或d开头的行尾添加管道。
在第一个空的空间区域中的第一个子替换管道。
第二个子管道放在NOT前面。