我有一个包含内容的文件:
abc|r=1,f=2,c=2
abc|r=1,f=2,c=2;r=3,f=4,c=8
我想要一个如下结果:
abc|r=1,f=2,c=2|1
abc|r=1,f=2,c=2;r=3,f=4,c=8|1
abc|r=1,f=2,c=2;r=3,f=4,c=8|3
第三列值为 r 值。每次出现都会插入一个新行。
我尝试过:
for i in `cat $xxxx.txt`
do
#echo $i
live=$(echo $i | awk -F " " '{print $1}')
home=$(echo $i | awk -F " " '{print $2}')
echo $live
done
但工作不正常。我是sed/awk
的初学者,不知道如何使用它们。有人可以帮忙吗?
答案 0 :(得分:2)
awk
救援!
$ awk -F'[,;|]' '{c=0;
for(i=2;i<=NF;i++)
if(match($i,/^r=/)) a[c++]=substr($i,RSTART+2);
delim=substr($0,length($0))=="|"?"":"|";
for(i=0;i<c;i++) print $0 delim a[i]}' file
abc|r=1,f=2,c=2|1
abc|r=1,f=2,c=2;r=3,f=4,c=8|1
abc|r=1,f=2,c=2;r=3,f=4,c=8|3
答案 1 :(得分:1)
使用内部例程(由 GNU grep
,sed
和tr
组成)编译第二个更精细的sed
命令,其输出需要进一步清理更多sed
。调用输入文件“ foo ”。
sed -n $(grep -no 'r=[0-9]*' foo | \
sed 's/^[0-9]*/&s#.*#\&/;s/:r=/|/;s/.*/&#p;/' | \
tr -d '\n') foo | \
sed 's/|[0-9|]*|/|/'
输出:
abc|r=1,f=2,c=2|1
abc|r=1,f=2,c=2;r=3,f=4,c=8|1
abc|r=1,f=2,c=2;r=3,f=4,c=8|3
查看内部sed
代码:
grep -no 'r=[0-9]*' foo | \
sed 's/^[0-9]*/&s#.*#\&/;s/:r=/|/;s/.*/&#p;/' | \
tr -d '\n'
它的目的是即时解析 foo (当 foo 更改时,输出也会更改),并在此实例中提出:
1s#.*#&|1#p;2s#.*#&|1#p;2s#.*#&|3#p;
这几乎是完美的,但它留在最后一行的旧数据中:
sed -n '1s#.*#&|1#p;2s#.*#&|1#p;2s#.*#&|3#p;' foo
abc|r=1,f=2,c=2|1
abc|r=1,f=2,c=2;r=3,f=4,c=8|1
abc|r=1,f=2,c=2;r=3,f=4,c=8|1|3
...旧数据|1
是最终sed 's/|[0-9|]*|/|/'
删除的内容。
答案 2 :(得分:1)
这是一个纯粹的bash
解决方案。我不建议实际使用此功能,但它可能有助于您更好地了解如何使用bash
中的文件。
# Iterate over each line, splitting into three fields
# using | as the delimiter. (f3 is only there to make
# sure a trailing | is not included in the value of f2)
while IFS="|" read -r f1 f2 f3; do
# Create an array of variable groups from $f2, using ;
# as the delimiter
IFS=";" read -a groups <<< "$f2"
for group in "${groups[@]}"; do
# Get each variable from the group separately
# by splitting on ,
IFS=, read -a vars <<< "$group"
for var in "${vars[@]}"; do
# Split each assignment on =, create
# the variable for real, and quit once we
# have found r
IFS== read name value <<< "$var"
declare "$name=$value"
[[ $name == r ]] && break
done
# Output the desired line for the current value of r
printf '%s|%s|%s\n' "$f1" "$f2" "$r"
done
done < $xxxx.txt
ksh
的更改:
read -A
代替read -a
。typeset
代替declare
。如果<<<
出现问题,您可以改用here here。例如:
IFS=";" read -A groups <<EOF
$f2
EOF