我有一个文件,我正在尝试从AWK中删除客户名称。 该文件是一个固定宽度的文件,每一列都有含义。
该文件由许多行组成,所有相同的格式,非常类似于以下内容:
1234-123 123456 12345678901234CUSTOMER NAME TO REMOVE12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
1234-123 123456 12345678901234CUSTOMER NAME TO REMOVE12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
1234-123 123456 12345678901234CUSTOMER NAME TO REMOVE12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
1234-123 123456 12345678901234CUSTOMER NAME TO REMOVE12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
我需要将客户名称与虚构名称交换,以便所需的输出为:
1234-123 123456 12345678901234SENTINAL PRIME 12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
1234-123 123456 12345678901234OPTIMUS PRIME 12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
1234-123 123456 12345678901234BUMBLE BEE 12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
1234-123 123456 12345678901234IRON HIDE 12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
我有一个我想用于此的转换器名称列表,存储在名为transformer.names
的文件中。
SENTINEL PRIME
OPTIMUS PRIME
BUMBLEBEE
IRONHIDE
但是,为了使原始文件的每一行保持相同的宽度,我需要用空格右键单击转换器名称,因为我拥有的转换器名称都是不同的长度。
似乎可以使用AWK将这些名称正确填充到一定长度,但是我还没有设法弄清楚(或找到足够清晰的答案(让我理解。
下面是我当前的 AWK 脚本。
#!/usr/bin/awk -f
BEGIN {
}
{
getline line < "transformer.names"
print substr($0, 0, 30) line substr($0, 62, 120)
}
我用这个命令运行它:
my_program.awk my-file.txt
我想我可以在上面的打印行中加入这样的行,但是我还没有设法让它工作。
printf "-%32s|", substr($0, 0, 30) line substr($0, 62, 120)
任何提示都太棒了!
您需要将%Ns
应用于要填充的特定字段而不是整行,并且您需要使减号(用于左垫/右对齐(成为说明符的一部分,并且printf
不会像print
那样自动添加行/记录分隔符,因此您需要添加:
printf "%s%-32s%sn", substr($0, 1, 30), newname, substr($0, 62, 120)
# note commas; this is a format string containing three specifiers,
# and separate three data values used for those three specifiers
或者,您可以填充字段,然后连接:
print substr($0,1,30) sprintf("%-32s", newname) substr($0,62,120)
# no commas except within the sprintf (and the substr's)
如果你的数据文件比你的"transformernames"文件有更多的行,那么你需要缓冲名称并反复循环,如Ravinder所示。
此外,awk 中的substr
位置从 1 开始; 如果您指定 0 或负数,则将其视为 1,但我认为实际说出您的意思更清楚,所以我修复了它。 62 不是您发布的示例数据中客户名称后面零件的正确起始位置,但您说数据仅与真实数据"非常相似", 所以我不知道 56 或 62 或其他东西是否正确。
您能否尝试关注并让我知道这是否对您有帮助。因此,它将具有所有转换器名称,假设它的值小于Input_file行,那么它将保持从它开始打印行。
awk '
FNR==NR{
a[FNR]=$0;
count=FNR;
next}
{
val=val==count?1:++val;
print substr($0,1,32) a[val]"tt"substr($0,56)
}' transformer.names Input_file
说明:现在也为上述代码添加说明。
awk '
FNR==NR{ ##Checking condition here FNR==NR which will be TRUE when first Input_file is being read.
a[FNR]=$0; ##Creating an array named a whose index is FNR and value is current line.
count=FNR; ##Creating variable count whose value is FNR value(current line number value of first Input_file).
next} ##next will skip further statements from here onward.
{ ##This block will execute when 2nd Input_file is being read.
val=val==count?1:++val; ##Creating variable val whose value is increment each time and when it is equal to count it is set to 1 then.
print substr($0,1,32) a[val]"tt"substr($0,56) ##Printing sub-string from 1 to 32 chars, value of a[val] TABs then sub-string from 56 char to till last of line.
}' transformer.names Input_file ##Mentioning Input_file(s) name here.
#!/usr/bin/awk -f
BEGIN {
}
{
getline line < "transformer.names"
printf("%s %-32s %s n", substr($0, 0, 30), line, substr($0, 62, 120))
}
你的问题几乎有答案!我只是复制了你的并对其进行了一点修改:)
您的数据似乎不是要修改的文本前的大写字母。
所以你可以试试这个尴尬。
awk '
FNR==NR {
a[NR]=$0
b=length()
len = len < b ? b : len
next
}
{
c = sprintf( "%-*2$s" , a[FNR], (len+1))
sub(/[A-Z][A-Z ]+/,c)
}
1' transformer_name customer_name
首先,我们将所有转换器名称放入数组 a 中,并将较大的长度保留在 len 中 在我们用新名称替换所有旧名称后,调整c中的
格式,您可以根据需要修改(len + 1(。
或者只使用FS
并跳过substr()
调用:
<小时 />mawk 'NF *=(__=FNR)==NR ? (___[__]=$_)*_ : (OFS=sprintf("%-24s",___[__]))^_' FS='CUSTOMER NAME TO REMOVE' <( echo 'SENTINEL PRIME OPTIMUS PRIME BUMBLEBEE IRONHIDE') -
1234-123 123456 12345678901234SENTINEL PRIME 12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
1234-123 123456 12345678901234OPTIMUS PRIME 12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
1234-123 123456 12345678901234BUMBLEBEE 12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
1234-123 123456 12345678901234IRONHIDE 12345-1234 TRN 123-123 12345678901-1234 TRN 12345678
这是一个使用column
为您执行所有右填充数学运算的解决方案 - 如果您的输入数据突然改变长度,但不能满足输出线长度与原始线长度匹配的OP要求,则非常方便:
cat my-file.txt |
awk '{getline line < "transformer.names";
print substr($0, 0, 30) line "|" substr($0, 62, 120)}' |
column -s'|' -t
可以使用gsub
和column
的组合,而无需抓取子字符串(或知道它们的长度(。
cat my-file.txt |
awk -v pipe='|'
'{getline line < "transformer.names";
gsub("CUSTOMER NAME TO REMOVE",line pipe,$0);
print $0}' |
column -s'|' -t
这里 ^ 我们在awk
中创建一个名为pipe
的变量,将其放置在替换gsub( ... line pipe ....)
内,然后将其用作稍后column
的分量仪。管道的使用是任意的。我们可以用星号(星号(做完全相同的事情:
cat my-file.txt |
awk -v star='*'
'{getline line < "transformer.names";
gsub("CUSTOMER NAME TO REMOVE",line star,$0);
print $0}' |
column -s'*' -t