我有一个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行),它起作用,但在它们之间创建空白行。我该如何解决?
答案 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中找到。