更改文本文件的两行

时间:2019-01-24 19:25:05

标签: linux bash awk

我有一个bash脚本,该脚本获取文本文件作为输入并接受两个参数(第N°行和第N°2行),然后在文本中将这两行彼此更改。这是代码:

#!/bin/bash

awk -v var="$1" -v var1="$2" 'NR==var {
    s=$0
    for(i=var+1; i < var1 ; i++) {
        getline; s1=s1?s1 "\n" $0:$0
    }
    getline; print; print s1 s
    next
}1' Ham > newHam_changed.txt 

对于每两行不连续的行,它工作正常。但对于彼此接续的行(例如第5行,第6行),它起作用,但在它们之间创建空白行。我该如何解决?

3 个答案:

答案 0 :(得分:2)

我认为您的实际脚本不是您在问题中发布的。我认为所有印刷品的行都包含:

print s1 "\n" s

问题在于,当行连续时,s1将为空(跳过for循环),但仍将在s之前打印换行符,从而产生空白线。

因此,您需要将该换行符作为条件。

awk -v var="4" -v var1="6" 'NR==var {
    s=$0
    for(i=var+1; i < var1 ; i++) {
        getline; s1=s1?s1 "\n" $0:$0
    }
    getline; print; print (s1 ? s1 "\n" : "") s
    next
}1' Ham > newHam_changed.txt 

答案 1 :(得分:1)

使用getline会使awk脚本总是有点复杂。最好不要使用getline,而只使用awk pattern { action }语法。这将使脚本可读性强。在任何其他语言中,您都可以循环执行并获得下一行,但是在awk中,我认为最好充分利用此功能。

awk -v var="$1" -v var1="$2" '
NR==var {s=$0; collect=1; next;}
NR==var1 {collect=0; print; printf inbetween; print s}
collect {inbetween=inbetween""$0"\n"; next;}
1' Ham

在这里,当我找到它时捕获s中的第一行并设置collect标志。这将在下一次迭代时触发collect块,该迭代将收集之间的所有行。每当找到第二行时,它会将collect设置回零,并首先打印当前行,而不是中间行,然后打印s。如果行是连续的,则它们之间为空,而printf将不执行任何操作。

答案 2 :(得分:0)

我觉得太复杂了,这很简单,可以完成相同的任务:

#!/bin/bash

ORIGFILE='original.txt'  # original text file
PROCFILE='processed.txt' # copy of the original file to be proccesed
CHGL1=`sed "$1q;d" $ORIGFILE`     # get original $1 line
CHGL2=`sed "$2q;d" $ORIGFILE`     # get original $2 line

`cat $ORIGFILE > $PROCFILE`

sed -i "$2s/^.*/$CHGL1/" $PROCFILE # replace 
sed -i "$1s/^.*/$CHGL2/" $PROCFILE # replace

更多代码并不意味着更有用,请保持简单。此代码不使用for,而是直接转到特定行。

编辑:

单行完成此任务的简单方法:

printf '%s\n' 14m26 26-m14- w q | ed -s file

this answer中找到。