【发布时间】:2019-08-25 15:57:33
【问题描述】:
任何想法如何编写 awk/sed 脚本来替换特定的标记值或模式(在这种情况下,PREV 来自与前一行不同列中的值?)
例如从上一行第一列的值中替换所有PREVs
a -> b
c -> PREV
d -> PREV
到:
a -> b
c -> a
d -> c
【问题讨论】:
-
是的。请edit您的问题展示您的尝试并告诉我们您需要帮助的地方。
任何想法如何编写 awk/sed 脚本来替换特定的标记值或模式(在这种情况下,PREV 来自与前一行不同列中的值?)
例如从上一行第一列的值中替换所有PREVs
a -> b
c -> PREV
d -> PREV
到:
a -> b
c -> a
d -> c
【问题讨论】:
$ awk 'NR>1{$3=p} {p=$1} 1' file
a -> b
c -> a
d -> c
【讨论】:
p 是一个变量,代表previous。 1 表示打印每一行
$ cat file
a -> b
c -> PREV
d -> PREV
e -> f # watch this record
g -> PREV
用 awk 替换上一行第一列的值中的所有 PREVs:
$ awk '$3=="PREV"{$3=prev}{prev=$1}1' file
输出:
a -> b
c -> a
d -> c
e -> f # watch this record
g -> e
【讨论】:
使用 GNU sed:
sed -E '/PREV/{G;s/PREV(.*)\n(\S+).*/\2\1/};h' infile
解释:
/PREV/ { # if the current line matches PREV
G # append hold space to pattern space
s/PREV(.*)\n(\S+).*/\2\1/ # replace PREV with first word from appended line,
# drop newline and rest of appended line
}
h # store pattern space in hold space
或者,为了便携性稍作修改:
sed '/PREV/{G;s/PREV\(.*\)\n\([^[:blank:]]\{1,\}\).*/\2\1/;};h' infile
【讨论】:
打高尔夫球:
$ awk '$3=p?p:$3; {p=$1}' file
a -> b
c -> a
d -> c
占$1==0:
$ awk '$3 = length(p)? p: $3; {p=$1}' <<EOF
a -> b
c -> PREV
d -> PREV
0 -> PREV
e -> PREV
f -> PREV
EOF
a -> b
c -> a
d -> c
0 -> d
f -> e
【讨论】:
如果您的数据在 d 文件中,请在 gnu sed 上尝试:
sed -Ez ':s s/((\S+)\s*->[^\n]+\n[^\n]*)PREV\s*/\1\2\n/;ts' d
【讨论】:
对于这个内容
$ cat file
a -> b
c -> PREV
d -> PREV
e -> PREV
g -> GOLD
p -> m
确保只替换 PREV 哨兵(其他保持原样):
$ awk 'NR>1 && /PREV/{$3=p}{p=$1} 1' file
a -> b
c -> a
d -> c
e -> d
g -> GOLD
p -> m
【讨论】: