为每个字段增强插入双引号

时间:2019-08-26 13:01:56

标签: perl awk sed

我正在根据下面提供的示例寻找下面的输入

样品

eno~ename~address~zip
123~abc~~560000~"a~b~c"
245~"abc ~ def"~hyd~560102
333~"ghi~jkl"~pub~560103
444~ramdev "abc def"~ram~10000

预期产量

"eno"~"ename"~"address"~"zip"
"123"~"abc"~""~"560000"~"a~b~c"
"245"~"abc ~ def"~"hyd"~"560102"
"333"~"ghi~jkl"~"pub"~"560103"
"444"~"ramdev ""abc def"""~"ram"~"10000"

当前代码:

awk 'BEGIN{s1="\"";FS=OFS="~"} {for(i=1;i<=NF;i++){if($i!~/^\"|\"$/){$i=s1 $i s1}}} 1' sample

当前代码不适用于最后一行。这是对insert quotes for each field using awk

的增强

1 个答案:

答案 0 :(得分:2)

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

cat <<\! | sed -Ef - file
:a;s/^([^"~][^~]*~+("[^~"]*"~+[^"~][^~]*~+)*[^"]*"[^"~]*)~/\1\n/;ta; #1
s/.*/~&/                                                             #2
s/~"([^"]*)"/~\1/g                                                   #3
s/"/""/g                                                             #4
s/.//                                                                #5
s/[^~]*/"&"/g                                                        #6
y/\n/~/;                                                             #7
!

此sed脚本的工作方式如下:

    字符串中的
  1. ~可以与字段定界符混淆。它们需要替换为当前行中不存在的唯一字符。由于sed使用换行符来分隔其输入,因此换行符无法在模式空间中显示,因此是此类字符的理想选择。字段由三种类型的字符串组成:

    a)不以双引号开头和结尾且没有引号的字符串。

    b)用双引号引起来的字符串

    c)不以双引号开头和结尾并且在其中用引号引起来的字符串。

    后面的字符串需要其中包含任何~才能替换\n。这可以通过以下方式实现:遍历当前行,留下类型a,b或c的字段,这些字段不包含~,而仅替换后面字符串中的~

    < / li>
  2. 为便于下一步操作,我们为第一个字符串引入了字段定界符。

  3. 删除所有包含双引号的字段(请参见1b)。

  4. 所有剩余的双引号都在类型1c的字符串中,并且可以通过在前缀"前面加引号。

  5. 现在删除步骤2中引入的初始字段定界符。

  6. 用双引号将所有字段引起来。

  7. 用其原始值~替换在步骤1中引入的换行符。

看来,GNU sed有一个错误,即如果翻译命令(y /../../)是脚本中的最后一个命令或一行命令,则需要在其后缀;

以上解决方案可以输入一长行:

sed -E ':a;s/^([^"~][^~]*~+("[^~"]*"~+[^"~][^~]*~+)*[^"]*"[^"~]*)~/\1\n/;ta;s/.*/~&/;s/~"([^"]*)"/~\1/g;s/"/""/g;s/.//;s/[^~]*/"&"/g;y/\n/~/;' file