如何在Shell脚本中转换Linux cpuset格式并实现遍历?
解决Linux sysfs CPU ID格式转Shell可遍历列表的问题
我之前也碰到过这个棘手的问题!sysfs里用0,2,4-6,8这种紧凑格式表示CPU集合,确实没法直接在Shell的for循环里遍历。下面给你分享两种实用的转换方法,能把它变成0 2 4 5 6 8这种空格分隔的常规格式:
方法一:纯Bash实现(无外部依赖)
这种方法不需要额外安装工具,完全用Bash内置命令就能完成,适合最小化系统或者对依赖要求严格的场景:
# 示例输入,也可以替换成$(cat /sys/devices/system/cpu/online) cpu_input="0,2,4-6,8" # 按逗号拆分输入为数组 IFS=, read -ra cpu_parts <<< "$cpu_input" # 初始化结果字符串 cpu_result="" # 遍历每个拆分后的元素 for part in "${cpu_parts[@]}"; do # 判断当前元素是否是范围格式(包含"-") if [[ "$part" == *-* ]]; then # 拆分范围的起始和结束值 IFS=- read start_cpu end_cpu <<< "$part" # 生成范围内的所有CPU ID for ((cpu_id=start_cpu; cpu_id<=end_cpu; cpu_id++)); do cpu_result+="$cpu_id " done else # 如果是单个CPU ID,直接添加到结果 cpu_result+="$part " fi done # 移除结果末尾多余的空格 clean_cpu_list=$(echo "$cpu_result" | sed 's/ $//') # 输出转换后的列表 echo "$clean_cpu_list"
执行后会输出:0 2 4 5 6 8,这时你就可以直接用for cpu in $clean_cpu_list; do ...; done来遍历了。
方法二:用Awk快速实现(简洁高效)
如果你系统里有Awk工具,一行命令就能搞定转换,代码更简洁:
# 直接转换输入字符串 echo "0,2,4-6,8" | awk -F, '{ for(i=1; i<=NF; i++) { split($i, range, "-") if (range[2]) { for(j=range[1]; j<=range[2]; j++) { printf "%d ", j } } else { printf "%d ", range[1] } } }' | sed 's/ $//'
如果要直接读取sysfs的CPU在线状态,把echo换成cat即可:
cat /sys/devices/system/cpu/online | awk -F, '{ for(i=1; i<=NF; i++) { split($i, range, "-") if (range[2]) { for(j=range[1]; j<=range[2]; j++) { printf "%d ", j } } else { printf "%d ", range[1] } } }' | sed 's/ $//'
两种方法都能完美解决问题,你可以根据自己的场景选择合适的方式~
内容的提问来源于stack exchange,提问作者Ryan
相关产品推荐
相关产品推荐

