UNIX:如何处理数据文件中单引号数据内的单引号

时间:2018-06-29 06:33:00

标签: unix

我必须从单引号中的数据中删除单引号:

'Hello'World';123;456
'Bye World';987;654

我正在使用以下命令:

awk -F"'" -v OFS="'" '{ for (i=2; i<=NF; i+=2) gsub(/\47/, "<\302\277>", $i) } 1'  c.txt >d.txt

这应将数据中的单引号转换为周转问号。但这不仅适用于单引号。如果我们用其他任何值代替"'"都可以。

我也尝试过:

awk -F"'" -v OFS="'" '{ for (i=2; i<=NF; i+=2) gsub("'"'"'", "<\302\277>", $i) } 1'  c.txt >d.txt

输出:

'Hello¿World';123;456
'Bye World';987;654

还有更多版本可用吗?

1 个答案:

答案 0 :(得分:2)

目标似乎是要识别以分号分隔的字段,并在其中将带引号的字符串内的单引号替换为反向引号(而不是替换标记字符串开头和结尾的单引号)。八进制数字047是单引号的字符代码。八进制字节\302\277以UTF-8编码U + 00BF(反问号)(相当于十六进制字节0xC2 0xBF)。我遵循的是“期望的输出”行,其中¿没有被尖括号(<>)包围。修改代码以包含尖括号很简单。

Awk不能像PCRE(与Perl兼容的正则表达式)那样容易地进行替换,但是可以这样做,如下所示:

 awk -F';' -v OFS=';' -v debug=0 \
    '{
        for (i = 1; i <= NF; i++)
        {
            if (debug && NF > 3) print NR ":" i ": <<" $i ">>"
            if ($i ~ /^..*\047.*.$/)
            {
                if (debug) print "[[" $i "]]"
                while (match($i, /^.[^\047]*\047/) > 0)
                {
                    if (RLENGTH == length($i)) break
                    prefix = substr($i, 1,RLENGTH - 1)
                    suffix = substr($i, RLENGTH + 1)
                    if (debug) print "[[" prefix "]] [[" suffix "]]"
                    $i = prefix "\302\277" suffix
                }
                if (debug) print "==" $i "=="
            }
        }
        print
     }' "$@"

可能还有其他替代机制,尤其是当您使用特定于Awk变体的功能时。 (您可以在脚本的第一行上设置debug=1来查看中间的打印输出。我通过使用\227而不是\277感到很困惑-C1控件字符0x97不可见。)

使用扩展数据集:

'Hello'World';123;456
'Bye World';987;654
'Punt'Boat'Pole';'Non-punctuated';''quote'';'mis'''quoted';'open;close'
'open'quoted;quoted'close';unopened'unclosed;9981

非调试输出为:

'Hello¿World';123;456
'Bye World';987;654
'Punt¿Boat¿Pole';'Non-punctuated';'¿quote¿';'mis¿¿¿quoted';'open;close'
'open¿quoted;quoted¿close';unopened¿unclosed;9981

对于debug=1,输出为:

[['Hello'World']]
[['Hello]] [[World']]
=='Hello¿World'==
'Hello¿World';123;456
'Bye World';987;654
3:1: <<'Punt'Boat'Pole'>>
[['Punt'Boat'Pole']]
[['Punt]] [[Boat'Pole']]
[['Punt¿Boat]] [[Pole']]
=='Punt¿Boat¿Pole'==
3:2: <<'Non-punctuated'>>
3:3: <<''quote''>>
[[''quote'']]
[[']] [[quote'']]
[['¿quote]] [[']]
=='¿quote¿'==
3:4: <<'mis'''quoted'>>
[['mis'''quoted']]
[['mis]] [[''quoted']]
[['mis¿]] [['quoted']]
[['mis¿¿]] [[quoted']]
=='mis¿¿¿quoted'==
3:5: <<'open>>
3:6: <<close'>>
'Punt¿Boat¿Pole';'Non-punctuated';'¿quote¿';'mis¿¿¿quoted';'open;close'
4:1: <<'open'quoted>>
[['open'quoted]]
[['open]] [[quoted]]
=='open¿quoted==
4:2: <<quoted'close'>>
[[quoted'close']]
[[quoted]] [[close']]
==quoted¿close'==
4:3: <<unopened'unclosed>>
[[unopened'unclosed]]
[[unopened]] [[unclosed]]
==unopened¿unclosed==
4:4: <<9981>>
'open¿quoted;quoted¿close';unopened¿unclosed;9981

请注意,如果您希望数据的最后一行将第一个分号视为被单引号括起来的字段内,则必须更努力地工作。除了其他问题之外,您还需要对字段的定义进行更精确(但很复杂)的定义。那时,Awk可能不是最好的工具。我会用Perl,但Python也可以做。