【问题标题】:Split multiple similar lines into two separate files with Bash使用 Bash 将多个相似的行拆分为两个单独的文件
【发布时间】:2015-05-21 16:25:55
【问题描述】:

我有一个包含多个子网的大文件,如下所示:

234.245.34.324/24
234.214.23.34/24
234.344.234.14/24
234.214.234.314/24
234.245.34.324/23
234.214.23.34/22
234.344.234.14/22
234.214.234.314/23
234.245.34.324/24
234.214.23.34/20
234.344.234.14/21
234.214.234.314/20

它们都具有不同的 IP 地址和相同的子网,例如我有 2340 个子网,/24

现在,我希望将这些拆分为 2 个文件,其中 50% 的所有 /24 拆分位于每个文件中,/23/22 /21 等也是如此。

我知道我可以与split -l 分开,但这只会给我电话。目的是让两个文件中的子网数量相等。

这应该在 Linux bash 中完成,因为它将是自动化的。

有人知道怎么做吗?

【问题讨论】:

  • 对不起,忘了说这应该在 linux bash 中完成,因为它会自动进行
  • 到目前为止你尝试过什么?请阅读How do I ask a good question?
  • 就个人而言,我首先会根据掩码大小过滤到一个文件(大概在一个临时目录中)——即。一个名为20 的文件包含所有/20s,一个名为19 的文件包含所有/19s 等;这与 GNU awk 无关;然后你只取每个文件的一半。
  • 嗨,到目前为止,我已经尝试过将这些行拆分到另一个文件中,但它仍然将它们保留在主文件中。 cat newsub.csv |排序-tr| awk '0 == NR % 2'
  • @kryd,这是否符合您按掩码长度过滤的意图?

标签: linux bash split


【解决方案1】:

假设您有可用的 bash 4.3,避免使用临时文件的实现可能如下所示:

#!/usr/bin/env bash
#      ^- important: use bash, not sh, as shell

# sort into an array per mask length
declare -A masklens=( )
while IFS=/ read -r addr masklen; do
  [[ $addr ]] || continue
  masklens[$masklen]=1
  declare -a "addrs_${masklen}"
  declare -n addrs="addrs_${masklen}"
  addrs+=( "$addr" )
done

exec 3>"$1" 4>"$2" # open output files
for masklen in "${!masklens[@]}"; do
  declare -n addrs="addrs_${masklen}"
  fmt="%s/${masklen}\n"
  printf "$fmt" "${addrs[@]:0:(${#addrs[@]} + 1) / 2}" >&3
  if (( ${#addrs[@]} > 1 )); then
    printf "$fmt" "${addrs[@]:(${#addrs[@]} + 1) / 2}" >&4
  fi
done
exec 3>&- 4>&- # close output files

...调用为...

$ splitfiles out1 out2 <infile

【讨论】:

  • 事实上我没有 bash 3.4,所以我从声明中收到了一些错误,但它似乎正在做它应该做的事情。我也必须使用 uniq -u 删除重复的行,但它似乎已经完成了魔法,谢谢
  • 如果没有declare -n,这肯定行不通;您的输出将是错误的(它将构建一个大数组,而不是每个掩码长度的数组并单独拆分它们)。
  • ...另外,如果在没有declare -n 的 bash 上运行它,您可能会得到重复的输出(为每个看到的 masklen 复制)。
猜你喜欢
  • 1970-01-01
  • 2019-11-17
  • 1970-01-01
  • 2022-10-07
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多