用另一个文件中的相应行替换文件的每个第4行

时间:2016-09-05 10:30:03

标签: replace sed

我有一种情况,我想用另一个文件中的相应行替换大文件的每个第4行,从第1行开始(第1行,第5行,第9行等)。

我尝试过使用sed,但无法弄清楚如何使用第二个文件的每第4行作为替换的输入。

到目前为止,我有:

sed '1~4 s/.*/?/' original-file.txt > output-file.txt

我可以使用什么而不是“?”正确地替换线?

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:4)

每当我看到的内容不仅仅是一个简单的思考时,我会从我的大脑中删除sed并尝试使用awk。可能我太awk - 有偏见,但我认为它存储数据的方式和访问行号的方式更好,更容易理解sed

所以,让我们使用the FNR==NR trick检查一个文件,然后检查另一个文件:

awk 'FNR==NR {data[FNR]=$0; next}  # store data from file 1
     (FNR%4==1){                   # in file 2, if line number is (4k + 1)
         $0=data[FNR]              # replace with the same line from the 1st file
     }1' file1 file2               # print the line

此处的关键是将文件1中的所有数据存储在数组data[]中,每行的索引为其行号。

然后,当读取文件2时,如果一个行的数字是4的倍数,则该行将替换为文件1的相应行。

请参阅序列从100到110的示​​例,其中包含1到10个交错的数字:

$ awk 'FNR==NR {data[FNR]=$0; next} (FNR%4==1){$0=data[FNR]}1' <(seq 10) <(seq 100 110)
1
101
102
103
5
105
106
107
9
109
110

答案 1 :(得分:0)

如果你不介意使用perl,这里有一个小脚本

#!/usr/bin/perl

open my $fh1,'<','original-file.txt' or die;
open my $fh2,'<','other-file.txt' or die;
open my $out,'>','output-file.txt' or die;
my $n=0;
while (<$fh1>) {
    my $s=<$fh2>;
    print $out ($n++ % 4 == 0 ? $s : $_);
}

这样可以避免将数据加载到内存中,从而在恒定的内存中运行。

答案 2 :(得分:0)

这可能适合你(GNU sed):

class CircleView: UIView {
    private var circleLayer: CAShapeLayer?

    override init(frame: CGRect) {
        super.init(frame: frame)
        self.commonInit()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.commonInit()
    }

    func commonInit() {
        self.tintColor = UIColor.lightGrayColor()
        self.backgroundColor = UIColor.clearColor()
    }

    override func drawRect(rect: CGRect) {
        super.drawRect(rect)
        self.drawCircle()
        self.addCircleAnimation()
    }
    override func animationDidStop(anim: CAAnimation, finished flag: Bool)
    {
        self.circleLayer?.removeFromSuperlayer()
    }

    func drawCircle() {
        let size:CGFloat = CGFloat(100)
        self.circleLayer?.removeFromSuperlayer()
        self.circleLayer = CAShapeLayer()
        self.circleLayer?.frame = self.bounds
        let radius = size / 2;
        let path = UIBezierPath(arcCenter: CGPointMake(size / 2, size / 2), radius: radius, startAngle: -CGFloat(M_PI) / 4, endAngle: 2 * CGFloat(M_PI) - CGFloat(M_PI) / 4, clockwise: true)
        self.circleLayer?.path = path.CGPath
        self.circleLayer?.fillColor = UIColor.clearColor().CGColor
        self.circleLayer?.strokeColor = self.tintColor.CGColor
        self.circleLayer?.lineWidth = CGFloat(2.0)
        self.circleLayer?.rasterizationScale = 2.0 * UIScreen.mainScreen().scale
        self.circleLayer?.shouldRasterize = true

        self.layer.addSublayer(self.circleLayer!)
    }


    /** UPDATED. Add animation for strokEnd instead of strokeStart **/
    func addCircleAnimation() {

        let animation = CABasicAnimation(keyPath: "strokeEnd")
        animation.delegate = self
        animation.fromValue = 0.0
        animation.toValue = 1.0

        animation.duration = CFTimeInterval(floatLiteral: 1)
        animation.removedOnCompletion = false
        animation.fillMode = kCAFillModeBackwards
        animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)

        animation.beginTime = CACurrentMediaTime()
        animation.delegate = self
        self.circleLayer?.addAnimation(animation, forKey:"strokeEnd")


    }
}

这使用了2次sed调用,并使用文件名sed '1~4!d' file2 | sed $'1~4{R/dev/stdin\n;d}' file1 > outFile 将第一个结果输入到第二个。还使用bashes /dev/stdin将换行符插入到第二个调用中。