替换相同范围内的数字

时间:2019-06-17 15:08:18

标签: awk sed

我有一个制表符delim file1,其中第一列看起来像

1
1
6
6
6
1A
1A
1B
2
2
2
2
3
4
4A
Z
Z

我想替换,以便1 = 1, 1A = 2, 1B = 3, 2 = 4, 3 = 5, 4 = 6, 4A = 7, 6 = 8, Z = 9 输出应为

1
1
8
8
8
2
2
3
4
4
4
4
5
6
7
9
9

我有其他帖子说,为避免累积替换,我应该从较大的值到较小的值进行工作,并使用以下方法进行多次替换:

sed -e 's/a/b/g ; s/b/d/g' file

但是我有60个替补。

有没有一种方法可以循环执行此操作或替代其他替代方法

请注意,每个元素重复不同的时间,它们可以是数字和字符,但是我将它们全部替换为数字1-60,并且以预定义的顺序而不是按照它们出现的顺序。我的文件中还有其他具有相同字符的列,但是我只想替换第一列中的内容。

5 个答案:

答案 0 :(得分:3)

使用以下搜索和替换字符串创建映射文件:

cat mapping
1   1
1A  2
1B  3
2   4
3   5
4   6
4A  7
6   8
Z   9

然后只需使用此awk即可在单个命令中获取所有替换项:

awk 'BEGIN{FS=OFS="\t"} NR == FNR{key[$1]=$2; next} $1 in key{$1=key[$1]} 1' mapping file

1
1
8
8
8
2
2
3
4
4
4
4
5
6
7
9
9

答案 1 :(得分:1)

能否请您尝试以下操作(如果您用TAB分隔了Input_file,并且也需要以TAB格式输出,请在unset($_SESSION[datos_form][__step__]);部分中添加其他FS=OFS="\t"

BEGIN

答案 2 :(得分:1)

对于单个数字前缀,无需手动映射即可使用

$ awk 'NR==FNR {a[$1]; next} 
       FNR==1  {asorti(a,b); for(k in b) c[b[k]]=k} 
               {print c[$1]}' file{,}

1
1
8
8
8
2
2
3
4
4
4
4
5
6
7
9
9

请注意,将6映射为8,而不是示例输出中的4。

答案 3 :(得分:1)

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

sed -E 's/$/\n:1=1:1A=2:1B=3:2=4:3=5:4=6:4A=7:6=8:Z=9/;s/^(\S+)(.*)\n.*:\1=([^:]*).*/\3\2/;P;d' file

将查找表追加到每一行,并使用模式匹配和向后引用将第一列转换为所需的字符串。

没有匹配查找的行将不会更改。

答案 4 :(得分:1)

由于您只想使用从1开始的连续数字作为替换,因此您所需要做的就是:

awk '
BEGIN {
    split("1 1A 1B 2 3 4 4A 6 Z",tmp)
    for (i in tmp) {
        map[tmp[i]] = i
    }
    FS = OFS = "\t"
}
$1 in map { $1 = map[$1] }
1' file
1
1
8
8
8
2
2
3
4
4
4
4
5
6
7
9
9
1