Linux 行内替换bash(使用变量将行替换为新行)

Linux 行内替换bash(使用变量将行替换为新行),linux,bash,text,sed,awk,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

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

文件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
然后使用sed内嵌替换将$line替换为$newLine


有没有更好的办法?这可能归结为变量的sed格式问题。

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

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格式,并且以防性别或年龄碰巧包含逗号。也许有人已经100万岁了

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

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格式,并且以防性别或年龄碰巧包含逗号。也许有人已经100万岁了

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

$ 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*
您可以在上面看到,以您喜欢的顺序打印您喜欢的任何字段是多么容易


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

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

$ 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*
您可以在上面看到,以您喜欢的顺序打印您喜欢的任何字段是多么容易


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

输入序列是否稳定?是否保证所有条目都出现在每一行中?如果不能保证它们都会出现,那么如何处理有年龄但没有性别的线条,或者有性别但没有年龄的线条?大概,既没有年龄也没有性别的行会被忽略?您将性别/年龄用作以后比较的输入是什么意思?另外,介意在CSV文件中显示一个示例行吗?您是否不需要名称作为参考来替换目标性别/年龄?CSV文件中的信息是否仅与一个人有关?像name和date这样的值上面有空格,对吗?另外,使用Ruby处理CSV文件更容易。可以使用*name*或任何其他字段包含空格吗?它能装冒号吗?您提到CSV,但我在您的输入中没有看到任何逗号-您发布的输入行是否真正代表您的实际输入?发布几行实际样本输入和预期输出。条目序列是否稳定?是否保证所有条目都出现在每一行中?如果不能保证它们都会出现,那么如何处理有年龄但没有性别的线条,或者有性别但没有年龄的线条?大概,既没有年龄也没有性别的行会被忽略?您将性别/年龄用作以后比较的输入是什么意思?另外,介意在CSV文件中显示一个示例行吗?您是否不需要名称作为参考来替换目标性别/年龄?CSV文件中的信息是否仅与一个人有关?像name和date这样的值上面有空格,对吗?另外,使用Ruby处理CSV文件更容易。可以使用*name*或任何其他字段包含空格吗?它能装冒号吗?您提到CSV,但我在您的输入中没有看到任何逗号-您发布的输入行是否真正代表您的实际输入?发布几行实际样本输入和预期输出。很好。这就是为什么您不使用shell来解析文本文件的原因-使用适合此工作的工具,即awk。@EdMorton您想建议我可以应用的实际改进吗?shell通常是重新格式化文本的一种很好的方法,因此我反对您的不明确的反对意见。我确实提出了一个改进建议—使用为操作文本而发明的工具,它具有简化文本操作所需的所有内置构造,并且在所有UNIX安装(即awk)上都可用。不知道我还能做些什么来更具体些。@EdMorton大多数情况下,你的评论只是挥舞着美国国旗,但这不是必须的,因为你的答案应该是独立的。如果您能指出您认为我的解决方案有哪些缺陷,说明为什么不应该使用shell解析文本文件,那么您的评论可能会更有建设性。我认为这些问题是不言而喻的。如果没有,我道歉。这里有一些
使用shell脚本解析文本文件的常见问题(以该脚本为例):它很长、复杂,并且数据与输入相耦合。请参见在shell脚本中使用特定键值作为变量和大小写。祝您好运。这就是为什么您不使用shell来解析文本文件的原因-使用适合此工作的工具,即awk。@EdMorton您想建议我可以应用的实际改进吗?shell通常是重新格式化文本的一种很好的方法,因此我反对您的不明确的反对意见。我确实提出了一个改进建议—使用为操作文本而发明的工具,它具有简化文本操作所需的所有内置构造,并且在所有UNIX安装(即awk)上都可用。不知道我还能做些什么来更具体些。@EdMorton大多数情况下,你的评论只是挥舞着美国国旗,但这不是必须的,因为你的答案应该是独立的。如果您能指出您认为我的解决方案有哪些缺陷,说明为什么不应该使用shell解析文本文件,那么您的评论可能会更有建设性。我认为这些问题是不言而喻的。如果没有,我道歉。下面是使用shell脚本解析文本文件的一些常见问题,该脚本就是一个例子:它很长,很复杂,并且数据与输入相耦合。请参见在shell脚本中使用特定键值作为变量和案例。