我遇到了一个对高级shell用户来说似乎不太难的问题。这是问题所在。
我有2个文件:
File1的格式如下:
ALPH 1 M GIF M 1 11.111 23.123 -4.412 1.00 0.00 A
ALPH 2 BA GIF M 1 22.222 78.251 -6.215 2.00 0.00 B
ALPH 3 C GIF M 1 22.223 46.321 -6.124 3.00 0.00 C
ALPH 4 D GIF M 1 23.333 15.214 -6.125 4.00 0.00 D
ALPH 5 AB GIF M 1 24.111 61.458 -8.214 5.00 0.00 E
ALPH 6 LM GIF M 1 25.333 78.214 -9.321 6.00 0.00 F
ALPH 7 BA GIF M 1 17.645 87.256 -9.365 7.00 0.00 G
ALPH 8 BA2 GIF M 1 14.125 19.365 -1.258 8.00 0.00 H
-
-
File2只有一列:
-0.14
-0.47
-0.58
-0.69
-0.25
-0.69
-0.12
-0.44
我想用File2中的唯一列替换File1中的第11列。我做了以下
paste File1 File2 | awk '{$11=$13;$13=""}1' > output
虽然它可以很好地替换列,但它会混淆我希望保留的File1的原始格式。正如您所看到的,File1的所有字段之间存在不同数量的空格,即使在替换$ 11之后我也希望保留这些空格。
我尝试了多种方法,包括column
和printf
,但似乎都没有。也许我做错了什么。
有没有人知道如何使用awk或sed来达到理想的效果?
谢谢!
罗希特夏尔
答案 0 :(得分:3)
当您为awk中的字段分配值时,它会使用OFS的当前值重新编译当前记录以分隔字段。要保留原始间距,则无法为字段指定新值。相反,您必须使用RE来描述在分配之前和之后要跳过的非空格/空格的数量。像这样取代字母" c" (第3个字段,因此数字" 2"下面是跳过的前导字段数),单词" BOB"使用GNU awk:
$ echo "a b c d e" |
gawk '{print gensub(/(([^[:space:]]+[[:space:]]+){2})[^[:space:]]+/,"\\1BOB","")}'
a b BOB d e
这会保留间距,因为您正在处理整个记录,而不仅仅是一个字段,因此awk不会重新编译记录。
因此,对于您的情况,它是:
$ cat file1
ALPH 1 M GIF M 1 11.111 23.123 -4.412 1.00 0.00 A
ALPH 2 BA GIF M 1 22.222 78.251 -6.215 2.00 0.00 B
ALPH 3 C GIF M 1 22.223 46.321 -6.124 3.00 0.00 C
ALPH 4 D GIF M 1 23.333 15.214 -6.125 4.00 0.00 D
ALPH 5 AB GIF M 1 24.111 61.458 -8.214 5.00 0.00 E
ALPH 6 LM GIF M 1 25.333 78.214 -9.321 6.00 0.00 F
ALPH 7 BA GIF M 1 17.645 87.256 -9.365 7.00 0.00 G
ALPH 8 BA2 GIF M 1 14.125 19.365 -1.258 8.00 0.00 H
$
$ cat file2
-0.14
-0.47
-0.58
-0.69
-0.25
-0.69
-0.12
-0.44
$
$ gawk 'NR==FNR{map[FNR]=$0; next} {print gensub(/(([^[:space:]]+[[:space:]]+){10})[^[:space:]]+/,"\\1" map[FNR],"")}' file2 file1
ALPH 1 M GIF M 1 11.111 23.123 -4.412 1.00 -0.14 A
ALPH 2 BA GIF M 1 22.222 78.251 -6.215 2.00 -0.47 B
ALPH 3 C GIF M 1 22.223 46.321 -6.124 3.00 -0.58 C
ALPH 4 D GIF M 1 23.333 15.214 -6.125 4.00 -0.69 D
ALPH 5 AB GIF M 1 24.111 61.458 -8.214 5.00 -0.25 E
ALPH 6 LM GIF M 1 25.333 78.214 -9.321 6.00 -0.69 F
ALPH 7 BA GIF M 1 17.645 87.256 -9.365 7.00 -0.12 G
ALPH 8 BA2 GIF M 1 14.125 19.365 -1.258 8.00 -0.44 H
如果你没有gawk(对于gensub()),你可以使用match()来查找你关心的字段的开始位置,第二个匹配()用于结束的位置,以及明智的substr() s用新值替换它。
@GlennJackman在他的解决方案中提到了固定宽度字段。如果您拥有的是什么,可以使用GNU awks FIELDWIDTHS变量来指定每个字段的宽度,并使用它。有关详细信息,请参阅gawk手册。
答案 1 :(得分:2)
使用awk
awk 'FNR==NR {a[NR]=$0;next} {$11=a[FNR]}1' OFS="\t" a t
ALPH 1 M GIF M 1 11.111 23.123 -4.412 1.00 -0.14 A
ALPH 2 BA GIF M 1 22.222 78.251 -6.215 2.00 -0.47 B
ALPH 3 C GIF M 1 22.223 46.321 -6.124 3.00 -0.58 C
ALPH 4 D GIF M 1 23.333 15.214 -6.125 4.00 -0.69 D
ALPH 5 AB GIF M 1 24.111 61.458 -8.214 5.00 -0.25 E
ALPH 6 LM GIF M 1 25.333 78.214 -9.321 6.00 -0.69 F
ALPH 7 BA GIF M 1 17.645 87.256 -9.365 7.00 -0.12 G
ALPH 8 BA2 GIF M 1 14.125 19.365 -1.258 8.00 -0.44 H
由于sub
的错误,修改已恢复原始状态
答案 2 :(得分:2)
如果您需要保留固定宽度列,则可以使用子字符串:
cat file1
echo
awk '
NR==FNR {v[FNR]=$1; next}
{print substr($0,1,62) sprintf("%-15s", v[FNR]) substr($0,78)}
' file2 file1
ALPH 1 M GIF M 1 11.111 23.123 -4.412 1.00 0.00 A
ALPH 2 BA GIF M 1 22.222 78.251 -6.215 2.00 0.00 B
ALPH 3 C GIF M 1 22.223 46.321 -6.124 3.00 0.00 C
ALPH 4 D GIF M 1 23.333 15.214 -6.125 4.00 0.00 D
ALPH 5 AB GIF M 1 24.111 61.458 -8.214 5.00 0.00 E
ALPH 6 LM GIF M 1 25.333 78.214 -9.321 6.00 0.00 F
ALPH 7 BA GIF M 1 17.645 87.256 -9.365 7.00 0.00 G
ALPH 8 BA2 GIF M 1 14.125 19.365 -1.258 8.00 0.00 H
ALPH 1 M GIF M 1 11.111 23.123 -4.412 1.00 -0.14 A
ALPH 2 BA GIF M 1 22.222 78.251 -6.215 2.00 -0.47 B
ALPH 3 C GIF M 1 22.223 46.321 -6.124 3.00 -0.58 C
ALPH 4 D GIF M 1 23.333 15.214 -6.125 4.00 -0.69 D
ALPH 5 AB GIF M 1 24.111 61.458 -8.214 5.00 -0.25 E
ALPH 6 LM GIF M 1 25.333 78.214 -9.321 6.00 -0.69 F
ALPH 7 BA GIF M 1 17.645 87.256 -9.365 7.00 -0.12 G
ALPH 8 BA2 GIF M 1 14.125 19.365 -1.258 8.00 -0.44 H
答案 3 :(得分:2)
这可能适合你(GNU sed):
sed = file2 | sed -r '$!N;s|(.*)\n(.*)|\1s/\\S+/\2/11|' | sed -rf - file1
答案 4 :(得分:1)
Pure awk解决方案:
awk 'FNR==NR{a[NR]=$0;next} {sub($11, a[FNR])}1' file2 file1
ALPH 1 M GIF M 1 11.111 23.123 -4.412 1.00 -0.14 A
ALPH 2 BA GIF M 1 22.222 78.251 -6.215 2.00 -0.47 B
ALPH 3 C GIF M 1 22.223 46.321 -6.124 3.00 -0.58 C
ALPH 4 D GIF M 1 23.333 15.214 -6.125 4.00 -0.69 D
ALPH 5 AB GIF M 1 24.111 61.458 -8.214 5.00 -0.25 E
ALPH 6 LM GIF M 1 25.333 78.214 -9.321 6.00 -0.69 F
ALPH 7 BA GIF M 1 17.645 87.256 -9.365 7.00 -0.12 G
ALPH 8 BA2 GIF M 1 14.125 19.365 -1.258 8.00 -0.44 H
答案 5 :(得分:0)
或者使用剪切:
cat file1 | cut -c 1-61 > section1
cat file1 | cut -c 67-80 > section2
paste section1 file2 section2 > output
文件格式看起来像一个 pdb 文件,字段之间的空白无关紧要,重要的是字段宽度