在线替换bash(使用变量替换新行)

时间:2013-09-21 22:01:27

标签: linux bash text sed awk

我正在浏览并从文件中读取行。他们有大量不必要的信息,我想重新格式化以供日后使用,以便我以后可以使用必要的信息。

文件(file1)中的示例行

Name: *name* Date: *date* Age: *age* Gender: *gender* Score: *score*

说我想从文件中提取性别和年龄,然后再使用

新行

*gender*, *age*

在bash中:

    while read line; do
       <store variable for gender>
       <store variable for age>
     <overwrite each line in CSV - gender,age>
     <use gender/age as inputs for later comparisons>  
     done < file1

编辑:条目没有稳定性。可以使用echo $line | cut找到一个值,使用[ $line =~ "keyValue" ]找到另一个值,然后设置该值

我在考虑将这两个变量的组合存储起来:

newLine="$val1,$val2"

然后使用sed内联替换将$line替换为$newLine

但是有更好的方法吗?它可能归结为变量的sed格式问题。

2 个答案:

答案 0 :(得分:2)

您的示例为解释留下了空间,因此我假设字段值中可能有空格,但字段值中没有冒号,并且每个字段键后跟冒号。我还假设订单稳定。

while IFS=: read _ _ _ age gender _; do
    age="${age% Gender}" # Use parameter expansion to strip off the key for the *next* field.
    gender="${gender% Score}"
    printf '"%s","%s"\n' "$gender" "$age"
done < file1 > file1.csv

更新

由于您的问题现在表明没有稳定性,您必须迭代可能的值以获得输出:

while IFS=: read -a line; do
    unset age key sex
    for chunk in "${line[@]}"; do
        val="${chunk% *}" # Everything but the key
        case "$key" in
            Age) age="$val";;
            Gender) sex="$val";;
        esac
        # The key is for the *next* iteration.
        key="${chunk##* }"
    done
    if [[ $age || $sex ]]; then
        printf '"%s","%s"\n' "$sex" "$age"
    fi
done < file1 > file1.csv

(另外,我在csv中的输出值周围添加了引号,以符合实际的csv格式,如果性别或年龄恰好有逗号,也许有人有1,000,000岁。)

答案 1 :(得分:2)

这将从您发布的示例输入中生成所需的输出:

$ cat file
Name: *name* Date: *date* Age: *age* Gender: *gender* Score: *score*

$ awk -F'[: ]+' -v OFS=', ' '{for (i=1;i<NF;i+=2) a[$i]=$(i+1); print a["Gender"], a["Age"]}' file
*gender*, *age*

$ awk -F'[: ]+' -v OFS=', ' '{for (i=1;i<NF;i+=2) a[$i]=$(i+1); print a["Score"], a["Name"], a["Date"] }' file
*score*, *name*, *date*

你可以看到上面按你喜欢的顺序打印你喜欢的任何字段是多么容易。

如果不是您想要的,请发布更具代表性的输入。