Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否有基于分隔符合并2个文件的特定bash命令?_Bash_Merge - Fatal编程技术网

是否有基于分隔符合并2个文件的特定bash命令?

是否有基于分隔符合并2个文件的特定bash命令?,bash,merge,Bash,Merge,我正在尝试将2个文件合并为1个文件,但具体方式不同。我目前使用嵌套的while循环执行此操作,但想知道是否有更简单的方法或命令。假设我有以下文件 文件1 文件2 B B B B B B B B 为了简化这个问题,我写了A和B,但文件中可以包含其他行。 这两个文件需要合并并保存到一个变量中,因为它将在我的bash程序中进一步使用,该变量必须包含以下内容: 1:A 2:B 2:B 1:A 1:A 1:A 2:B 2:B 2:B 2:B 2:B 2:B # read file as a bl

我正在尝试将2个文件合并为1个文件,但具体方式不同。我目前使用嵌套的while循环执行此操作,但想知道是否有更简单的方法或命令。假设我有以下文件

文件1

文件2

B
B

B
B
B
B

B

B
为了简化这个问题,我写了A和B,但文件中可以包含其他行。 这两个文件需要合并并保存到一个变量中,因为它将在我的bash程序中进一步使用,该变量必须包含以下内容:

1:A
2:B
2:B
1:A
1:A
1:A
2:B
2:B
2:B
2:B
2:B
2:B
# read file as a blank-line-separated array
readlines() {
    local file="$1"
    local -n array="$2"
    local num="$3"
    local line
    local i=0
    while IFS= read -r line; do
        if [[ -z $line ]]; then
            ((i++))
        else
            array[i]+="$num:$line"$'\n'
        fi
    done < "$file"
}

min() {
    local x="$1"
    local y="$2"
    if (( x < y )); then
        echo "$x"
    else
        echo "$y"
    fi
}

declare -a a b
readlines "file1" "a" "1"
readlines "file2" "b" "2"
m=$(min "${#a[@]}" "${#b[@]}")

# interleaving part
for (( i=0; i<m; i++ )); do
    echo -n "${a[i]}${b[i]}"
done

# remaining part
if (( ${#a[@]} < ${#b[@]} )); then
    for (( i=m; i<${#b[@]}; i++ )); do
        echo -n "${b[i]}"
    done
else
    for (( i=m; i<${#a[@]}; i++ )); do
        echo -n "${a[i]}"
    done
fi
正如您所看到的,如果一个文件有多个组(一个组是多行,没有空行),则文件会根据换行符合并在一起,而不是仅在彼此之后添加。此外,还必须根据行来自哪个文件添加1或2。是否有一个简单的命令(而不是awk)来解决这个问题,而不是嵌套的whiles

更多信息编辑


这两个文件必须用分隔符“空行”合并,这样您可以从file1的第一行开始,直到一个空行,然后添加file2的行,直到一个空行。如果一个文件没有更多的行,则只会添加另一个文件的其他行。这些行还必须有一个指示,指示这些行是来自文件1还是文件2。

是否尝试以下操作:

1:A
2:B
2:B
1:A
1:A
1:A
2:B
2:B
2:B
2:B
2:B
2:B
# read file as a blank-line-separated array
readlines() {
    local file="$1"
    local -n array="$2"
    local num="$3"
    local line
    local i=0
    while IFS= read -r line; do
        if [[ -z $line ]]; then
            ((i++))
        else
            array[i]+="$num:$line"$'\n'
        fi
    done < "$file"
}

min() {
    local x="$1"
    local y="$2"
    if (( x < y )); then
        echo "$x"
    else
        echo "$y"
    fi
}

declare -a a b
readlines "file1" "a" "1"
readlines "file2" "b" "2"
m=$(min "${#a[@]}" "${#b[@]}")

# interleaving part
for (( i=0; i<m; i++ )); do
    echo -n "${a[i]}${b[i]}"
done

# remaining part
if (( ${#a[@]} < ${#b[@]} )); then
    for (( i=m; i<${#b[@]}; i++ )); do
        echo -n "${b[i]}"
    done
else
    for (( i=m; i<${#a[@]}; i++ )); do
        echo -n "${a[i]}"
    done
fi
[编辑]

上面的脚本确实有效,但一点也不有趣。
我重新考虑使用
paste
命令:

paste -d '' <(sed '/.\+/s/.\+/1:&/' file1 | tr '\n' '#' | sed 's/##/#\'$'\n/g') \
    <(sed '/.\+/s/.\+/2:&/' file2 | tr '\n' '#' | sed 's/##/#\'$'\n/g') \
    | tr -d '\n' | tr '#' '\n'
使用GNU-sed粘贴-d':

paste -z -d $'\n' <(
      sed 's/^$/\x00/;t;s/^/1:/' file1.txt) <(
      sed 's/^$/\x00/;t;s/^/2:/' file2.txt) |
sed 's/\x00//g;/^$/d'

paste-z-d$'\n'不清楚,请您在问题中提供更多细节,特别是获取样本输出的逻辑,请在完成后告诉我们。我添加了更多信息。问题非常好!但是,在没有awk的情况下这样做比使用awk更具挑战性awk@fangio,不应该持续2个
B
s就像
1:B
一样,因为只有1个B是连续的,如果我在这里错了,很抱歉。这是一个很好的例子,可以说明为什么awk是执行此类任务的合适工具++尝试使用
cat
而不是粘贴!我为什么要这么做!我需要将file2.txt中的第二个“block”放在file1.txt中的第二个“block”之后。