使awk为输出保持输入格式间距不变

使awk为输出保持输入格式间距不变,awk,Awk,我想打印输入列ASCII数据文件,只修改某些特定列。 如果我使用awk修改列(例如:$NF=99),当我最终给出“print$0”命令时,它会正确打印输出,但其他列的所有空格填充、格式设置等都消失了。(它们基本上都被OFS取代) 有没有办法让awk打印完全相同的输入,只在指定的列中进行更改? 我需要将此输出提供给另一个fortran代码,它具有非常严格的读取格式。因此,我无法更改行的格式 如果awk不是我应该使用的软件,你有什么建议 更新:示例: 在一行中输入条目 0 0 0 0 0 0 0

我想打印输入列ASCII数据文件,只修改某些特定列。 如果我使用awk修改列(例如:$NF=99),当我最终给出“print$0”命令时,它会正确打印输出,但其他列的所有空格填充、格式设置等都消失了。(它们基本上都被OFS取代)

有没有办法让awk打印完全相同的输入,只在指定的列中进行更改? 我需要将此输出提供给另一个fortran代码,它具有非常严格的读取格式。因此,我无法更改行的格式

如果awk不是我应该使用的软件,你有什么建议


更新:示例:

在一行中输入条目

0 0 0 0 0 0 0  1936 24170  2536  1987 24094  2543  2037 24153  2550  2088 24202  2557 27 24 24.5 10000.0    0.31     0.0 10000.0     0.0     0.0     0.0    0.65
我想将该条目转换为

0 0 0 0 0 0 0  1936 24170  2536  1987 24094  2543  2037 24153  2550  2088 24202  2557 27 24 24.5 10000.0 10000.0 10000.0 10000.0 10000.0 10000.0 10000.0 10000.0
重要的是保持其他柱的间距和位置完整


为了完成我的任务,我能做的最接近的事情是下面的命令

gawk '{output=$0;for (i=0;i<8;i++){output=substr(output,0,97+8*i-1)"10000.0"substr(output, 97+8*(i+1)-1)}; print output}'

gawk'{output=$0;for(i=0;i你对自己所做的事情不太具体,所以我在这里不能具体说明。也就是说:


听起来你需要做的是让你的代码直接修改
$0
,而不是选择一个字段。
sub()
gsub()
可能对你有用,或者你可以使用
match()

来“找到”一个字段。你对你正在做的事情不太具体,所以我在这里不能具体说明。也就是说:


听起来你需要做的是让你的代码直接修改
$0
,而不是选择一个字段。
sub()
gsub()
可能对你有用,或者你可以使用GNU awk使用
match()
找到一个字段,下面是如何用“替换”一词替换第三个字段:

在其他AWK中,您可以对sub()s或match()+substr()s执行相同的操作

要保持字段结束位置,假设替换文本小于或等于原始文本的长度加上其前面的空格:

$ cat file
field1      field2           field3    field4
  field1      field2           field3    field4

$ awk -v fieldNr=3 -v text="replacement" -f tst.awk file
field1      field2      replacement    field4
  field1      field2      replacement    field4

$ cat tst.awk
BEGIN {
    preFld="^([[:space:]]*[^[:space:]]+){" fieldNr-1 "}"
}
{
    match($0,preFld)
    head = substr($0,RSTART,RLENGTH)

    match($0,preFld "[[:space:]]*[^[:space:]]+")
    field = substr($0,RSTART+length(head),RLENGTH-length(head))

    printf("%s% *s%s\n", head, length(field), text, substr($0,RSTART+RLENGTH))
}

有关此主题和不同解决方案的更多信息,请尝试GNU gawk“patsplit()”函数和/或FIELDWIDTHS变量。

对于GNU awk,以下是如何用“替换”一词替换第三个字段:

在其他AWK中,您可以对sub()s或match()+substr()s执行相同的操作

要保持字段结束位置,假设替换文本小于或等于原始文本的长度加上其前面的空格:

$ cat file
field1      field2           field3    field4
  field1      field2           field3    field4

$ awk -v fieldNr=3 -v text="replacement" -f tst.awk file
field1      field2      replacement    field4
  field1      field2      replacement    field4

$ cat tst.awk
BEGIN {
    preFld="^([[:space:]]*[^[:space:]]+){" fieldNr-1 "}"
}
{
    match($0,preFld)
    head = substr($0,RSTART,RLENGTH)

    match($0,preFld "[[:space:]]*[^[:space:]]+")
    field = substr($0,RSTART+length(head),RLENGTH-length(head))

    printf("%s% *s%s\n", head, length(field), text, substr($0,RSTART+RLENGTH))
}

有关主题和不同解决方案的更多信息,请尝试GNU gawk“patsplit()”函数和/或FIELDWIDTHS变量。

如果字段是固定宽度的,是否考虑过不按字段编号而按列编号进行更改?可以通过substr()在awk中进行更改,也可以使用cut

e、 g.假设您想要的字段总是在第56-60列中,您可以这样做
打印substr($0,1,55)“text!”substr($0,61);

如果字段是固定宽度的,您是否考虑过不按字段编号而按列编号进行更改?您可以通过substr()在awk中执行此操作,也可以使用cut

e、 g.假设您想要的字段总是在第56-60列中,您可以这样做
打印substr($0,1,55)“文本!”substr($0,61)

如果你能具体一点,包括一个输入文件示例和预期的输出,这会有所帮助。这个示例有些帮助,但仍然不清楚:你是否只想用
10000.0
替换最后8列数字?与上面的示例不同,我想替换给定字段(如$10、$13等)。我会注意,我不会让它插入任何大于可用空格填充的空间的内容。如果您可以具体说明,包括一个示例输入文件和预期输出,这会有所帮助。该示例有些帮助,但仍然不清楚:您是否只想将最后8列数字替换为
10000.0
?与上面的示例不同,我想替换给定字段(如$10、$13等)。我会注意,我不会让它插入任何大于可用空格填充的空间的内容。谢谢你的建议。我添加了一个示例。谢谢你的建议。我添加了一个示例。谢谢你的示例。我想保持替换右侧列的位置也与输入中的位置完全相同。我已经在我的问题中添加了一个例子来说明这一点。你说你想保留间距和位置,但除非替换字段的宽度与原始字段的宽度相同,否则你不能同时保留这两个字段。看起来你真正想要的是保留位置,而不是与你发布的问题完全不同的间距。我会注意的我不插入任何大于字段允许空间的内容。通过“保留间距”,我的意思是其他列的间距,我不会更改。[您建议使用substr()已经解决了这部分问题]感谢您提供的示例。我想保持替换右侧列的位置与输入中的位置完全相同。我在上面的问题中添加了一个示例,以明确说明这一点。您说您希望保持间距和位置,但不能同时保持间距和位置,除非替换字段的宽度与原始字段的宽度相同。看起来就像您所说的我真正想要的是保留位置,而不是间距,这与您发布的问题完全不同。我会注意,我不会插入任何大于该字段允许的空间的内容。通过“保留间距”,我的意思是其他列的间距,我不会更改。[您建议使用substr()已经解决了这部分问题]因为要替换的字段每次都会更改。我想我应该制作一个查找表,将每个对应字段的位置存储在列中,并在那里进行替换,如您所述。谢谢,因为要替换的字段每次都会更改。我想我应该制作一个查找表,将位置存储在列中