使用Bash one-liner来屏蔽文件中的数据

时间:2014-02-07 09:39:07

标签: bash sed awk

我有一个非常大的文件。我需要屏蔽特定位置和特定记录类型中的所有字符。我搜遍了所有地方,但找不到这个非常简单的任务的解决方案。这是一个例子

文件名:hello.txt

文件:

0120140206INPUT FILE
1032682842 MR SIMPSON
20231458 742 Evergreen Terrace
3034560817 GREEN
1032682842 MR GRIFFIN
20231458 Spooner Street
3034560817 RED
3001 

我想做的是屏蔽以“10”开头的所有行的12-16位。像这样:

0120140206INPUT FILE
1032682842 XXXXXMPSON
20231458 742 Evergreen Terrace
3034560817 GREEN
1032682842 XXXXXIFFIN
20231458 Spooner Street
3034560817 RED
3001

8 个答案:

答案 0 :(得分:4)

使用sed

sed -r '/^10/ s/^(.{11}).{5}/\1XXXXX/' file

0120140206INPUT FILE
1032682842 XXXXXMPSON
20231458 742 Evergreen Terrace
3034560817 GREEN
1032682842 XXXXXIFFIN
20231458 Spooner Street
3034560817 RED
3001

解释

  • -r sed中的有用选项--regexp-extended
  • /^10/搜索以10开头的行。
  • s/^(.{11}).{5}/\1XXXXX/掩码位置12-16到XXXXX

同样的想法,如果你的awk是gawk,并支持gensub()函数:

awk '{$0=gensub(/^(10.{9}).{5}/,"\\1XXXXX",$0)}1' file

更新:@tripleee提供更短的一个:

sed -r 's/^(10.{9}).{5}/\1XXXXX/' file

答案 1 :(得分:2)

这可以是一种方式:

$ awk 'BEGIN{FS=OFS=""} $1$2=="10" {for(i=12;i<=16;i++) $i="X"}1' file
0120140206INPUT FILE
1032682842 XXXXXMPSON
20231458 742 Evergreen Terrace
3034560817 GREEN
1032682842 XXXXXIFFIN
20231458 Spooner Street
3034560817 RED
3001

解释

  • BEGIN{FS=OFS=""}将字段分隔符设置为“”,这样第一个字符将是第一个字段,第二个字符将是第二个字段...
  • $1$2=="10" {for(i=12;i<=16;i++) $i="X"}如果第一个字符为1,第二个字符为0,则从第12个字符更改为第16个字符为X
  • 1 true condition,被评估为默认的awk行为:{print $0}

答案 2 :(得分:1)

这个awk可以工作:

awk '/^10/{q=substr($0, 12, 4); gsub(/./, "*", q); $0=substr($0, 1, 11) q substr($0, 17)}1' file

答案 3 :(得分:0)

这应该做:

awk '/^10/{q=substr($0,1,11);r=substr($0,17); $0=q "XXXXX" r }1' file
0120140206INPUT FILE
1032682842 XXXXXMPSON
20231458 742 Evergreen Terrace
3034560817 GREEN
1032682842 XXXXXIFFIN
20231458 Spooner Street
3034560817 RED
3001

答案 4 :(得分:0)

这可能适合你(GNU sed):

sed -r '/^10/{s/^(.{0,11})(.{0,5})/\1\n\2\n/;h;s/[^\n]/X/g;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2\1/}' file

对于以10开头的行:在预期蒙版的两侧放置两个标记,复制,用掩码字符替换标记以外的所有字符,附加副本并操纵标记之间的文本以定位掩模。

N.B。这适合短线,不会引入人工制品。

答案 5 :(得分:0)

您可以使用gawk固定宽度数据读取功能:

gawk -v FIELDWIDTHS="11 5 9999" -v OFS="" '/^10/ { $2 = "XXXXX" } ; { print }' file

请参阅https://www.gnu.org/software/gawk/manual/gawk.html#Constant-Size

答案 6 :(得分:0)

您可以使用BASH:

while read f1 f2; do
    if [[ $f1 =~ ^10 ]]; then
            f2="XXXXX${f2:5}"
    fi
    echo $f1 $f2
done < hello.txt

如果你只需要用XXXXX替换第二个字段的前5个字符,这将有效。

如果你需要用XXXXX替换第12个到第16个字符而不考虑字段,你可以做更长的时间:

while read l; do
    if [[ $l =~ ^10 ]]; then
            b=${l:11}
            e=${l:16}
            t=${b/$e/}
            l=${l/$t/XXXXX}
    fi
    echo $l
done < hello.txt

答案 7 :(得分:0)

perl替代

perl -p -i -e 's/^(10\d* )[A-Z ]{6}(.*)/$1XXXXXX$2/g' filename.txt