我想知道如何更改文件中一行的位置(最好使用sed)。例如,考虑包含
的文件goal identifier statement
let statement 1
let statement 2
forall statement
other statements
我希望能够做到这一点
goal identifier statement
forall statement
let statement 1
let statement 2
other statements
我改变 forall 行的位置,然后将其带到目标行之后。 forall 和目标是可用于识别行的正则表达式。
答案 0 :(得分:5)
您可以尝试将line 4
移至line 2
,我想将line A
移至line B
,其中A>B
sed -n '2{h; :a; n; 4{p;x;bb}; H; ba}; :b; p' file
或A<B
sed -n '2{h; d}; 4{p; x;}; p' file
你得到的,在第一种情况下:将line 4
移至line 2
goal identifier statement
forall statement
let statement 1
let statement 2
other statements
你得到的,在第二种情况下:将line 2
移至line 4
goal identifier statement
let statement 2
forall statement
let statement 1
other statements
<强>解释强>
sed -n ' #silent option ON
2{ #if is line 2
h #Replace the contents of the hold space with the contents of the pattern space
:a #label "a"
n #fetch the next line
4{ #if is line 4
p #print line 4
x #Exchange the contents of the hold and pattern spaces
bb #goto "b"
}
H #appends line from the pattern space to the hold space, with a newline before it.
ba #goto "a"
}
:b #Label "b"
p #print
' file
修改强>
如果您想使用regex
来识别线条,可以修改第一个命令
sed -n '/goal/{p;n;h;:a;n;/forall/{p;x;bb};H;ba};:b;p' file
答案 1 :(得分:1)
$ cat r.awk
BEGIN {
forall_re = "^forall" # examples of regexps
goal_re = "^goal"
}
function tag(l) { # tag a line
if (l ~ goal_re ) return "goal"
else if (l ~ forall_re) return "forall"
else return "rest"
}
{ # store entire file in array; give a tag to every line
lines[NR] = $0
tags[NR] = tag($0)
}
function swap0(a, i, j, tmp) {
tmp = a[i]; a[i] = a[j]; a[j] = tmp
}
function swap(i, j) {
swap0(lines, i, j); swap0(tags, i, j)
}
function rise(i) {
# TODO: add error check
while (i - 1 > 0 && tags[i - 1] != "goal") {
swap(i, i - 1); i--
}
}
function process( i) {
for (i = 1; i <= NR; i++)
if (tags[i] == "forall") rise(i)
}
function dump( i) { # print the array
for (i = 1; i <= NR; i++)
print lines[i]
}
END {
process()
dump()
}
输入文件的示例
$ cat r.txt
goal identifier statement
let statement 1
let statement 2
forall statement A
other statements
goal identifier statement
let statement 1
let statement 2
forall statement B
other statements
用法:
$ awk -f r.awk r.txt
goal identifier statement
forall statement A
let statement 1
let statement 2
other statements
goal identifier statement
forall statement B
let statement 1
let statement 2
other statements
答案 2 :(得分:1)
sed用于单个行上的简单替换,即全部。对于其他任何事情,你应该使用awk来获得软件的每个理想属性(清晰度,简单性,可移植性等等):
$ awk 'NR==FNR{if (/forall/) {f=FNR; v=$0} next} FNR!=f; /goal/{print v} ' file file
goal identifier statement
forall statement
let statement 1
let statement 2
other statements
答案 3 :(得分:0)
sed -r '/goal/{ # if match "goal" line
:X # this is a lable for branch command
N # append next line
/forall[^\n]*$/{ # if match "forall" line move to "goal" line below
s#^([^\n]*)(.*)(\n[^\n]*)$#\1\3\2#
b # after move finished branch to end
}
bX # branch to :X for appending next line
}' file
goal identifier statement
forall statement
let statement 1
let statement 2
other statements
答案 4 :(得分:0)
使用vim使用正则表达式$ REGEX_EXPRESSION在$ FILENAME中查找一行并将该行移至$ LINE_NUMBER的一种不太可怕的方式:
vim -c "g:$REGEX_EXPRESSION:m$LINE_NUMBER" -cwq "$FILENAME"
说明:-c
是vim中的命令,因此它会转到与该正则表达式匹配的第一行,然后将其移至指定的行号,然后执行命令wq
(或写入并放弃)。