2

这里 r 2 文件

--------------文件a--------------

1,2,3
2,xx,yy
3,lllll,ddd

------------文件b---------------

8,55
9,555
100,5555

我想要的结果是:文件a-------------

8,2,3
9,xx,yy
100,lllll,ddd

所以 bash 是:

#!/bin/bash
for i in $(seq 3)
do
q=`awk -v aa=$i -F , 'NR==aa{print $1}' a`
qq=`awk -v aa=$i -F , 'NR==aa{print $1}' b`
sed -i "s/^$q/$qq/g" a 
done

这里没有错误

但如果发生错误:

#! /bin/bash
for i in $(seq 3)
do
q=`awk 'BEGIN {FS=","} NF!=1{print $1}' a`
qq=`awk 'BEGIN {FS=","} NF!=1{print $1}' b`
sed -i "s/^$q/$qq/g" a
done

这是错误

sed:-e 表达式 #1,字符 4:未终止的 `s' 命令

这个错误是怎么发生的?


THX to @EdMorton q 在 awk 执行时有 3 行,所以 sed 发生错误。q 应该拆分执行 sed,所以

#! /bin/bash
q=`awk 'BEGIN {FS=","} {print $1}' a`
qq=`awk 'BEGIN {FS=","} {print $1}' b`
for ((i=1;i<=3;++i))
do
    a=`echo $q | cut -d" " -f $i`
    aa=`echo $qq | cut -d" " -f $i`
    sed -i "s/^$a/$aa/g" a
    echo $a
done

所以错误消失了我在这里使用 cut 将 q 拆分为 3 个字段,但它的冗余和 THX 到 @user000001 ,答案很清楚 **但是如果每个文件的字段和行都不同,粘贴不合适

#! /bin/bash
so i vi a bash:
len1=`awk -v x=1 -F, '{if(NR>x){x=NR}}END{print x}' a`
len2=`awk -v x=1 -F, '{if(NR>x){x=NR}}END{print x}' b`
if ((len1>len2))
then
        ((yy=2*len2))

else
        ((yy=len1+len2))
fi
q=`awk -v begin="$len2" -v end="$yy"  'BEGIN{FS=OFS=",";ORS="\n";}{if(NR<=end-begin)  {arr[FNR]=$1;next}else if(NR>begin&&NR<=end){$1=arrFNR];print $0}}' b a`
echo $q

顺便说一句,如果上述 bash 的结果:8,2,3,7,4 9,xx,yy 100,llllll,ddd 1000,aloha,ee 没有“\n”为什么?


@EdMorton 超过 2 个文件怎么样(或者我不知道我有多少个文件):

----文件a-------------文件b------------文件c---------

1,2,3,4,7-------------8,55--------------99,3$

2,xx,yyd---------------9,5555-----------999​​,43

3,llllll,ddd------------100,5555---------999​​9,533

4,阿罗哈,ee----------1000,77

-----------------------10000,567

** * * *我想要的结果是:

----文件a---------------文件b------------文件c---------

8,2,3,4,7--------------99,55-------------99,3$

9,xx,yyd---------------999​​,5555----------999​​,43

100,llll,ddd----------999​​9,5555---------999​​9,533

1000,阿罗哈,ee--------1000,77

-----------------------10000,567

什么是最短的 bash/awk/... 命令?

4

3 回答 3

3

只需使用 awk:

$ awk 'BEGIN{FS=OFS=","} NR==FNR{a[NR]=$1;next} {$1=a[FNR]} 1' b a
8,2,3
9,xx,yy
100,lllll,ddd

当您使用带双引号的 sed 时,您会招来鼻恶魔,因为脚本中的 shell 变量在 sed 执行之前会被扩展,因此存储在这些变量中的任何字符都会成为脚本的一部分。如果使用得当,Awk 就不存在这个问题。第二个脚本中使用的 awk 命令产生多行输出,因此 sed 可以看到换行符和阻塞。

于 2013-09-10T11:59:07.680 回答
2

A single call to awk will do the trick:

$ awk 'NR==FNR{a[NR]=$2FS$3;next}{print $1,a[FNR]}' FS=, OFS=, file1 file2
8,2,3
9,xx,yy
100,lllll,ddd
于 2013-09-10T11:53:05.593 回答
2

cut您可以使用and代替 awk paste。例如:

$ paste -d, <(cut -d, -f 1 fileb) <(cut -d, -f 2- filea) 
8,2,3
9,xx,yy
100,lllll,ddd

给出你想要的结果。

于 2013-09-10T11:50:39.927 回答