jq实现对url拼接

var url_build = function (path, params) {
        var url = "" + path;
        var _paramUrl = "";
        // url 拼接 a=b&c=d
        if(params){
            _paramUrl = Object.keys(params).map(function (k) {
                return [encodeURIComponent(k), encodeURIComponent(params[k])].join("=");
            }).join("&");
            _paramUrl = "?" + _paramUrl
        }
        return url + _paramUrl
    }

解释

  1. params 对象形如:{“id”:1, “q”:2}
  2. encodeURIComponent 将sring字符串作为URI组件进行编码
  3. 拼接成形如http://www.baidu.com/?id=1@q=2的样式
<think>我们有一个需求:轮询获取HTTP API操作结果并处理分页数据。 根据之前的讨论,我们已经知道如何使用curl进行API调用,以及如何解析JSON响应(使用jq)。 现在,我们需要处理分页数据。通常,分页API会在响应中包含分页信息(如当前页码、总页数、下一页的URL或页码等)。 步骤: 1. 设计一个循环,用于轮询操作结果(如果操作是异步的,可能需要等待操作完成)。 2. 当操作完成后,获取结果数据,并且结果可能是分页的。 3. 处理分页:循环获取每一页的数据,直到没有下一页。 假设: - 我们有一个初始的API端点来获取操作状态(可能返回一个结果URL,或者结果直接分页返回)。 - 当操作完成后,状态变为“COMPLETED”,然后我们可以获取结果。 - 结果分页的常见形式:在响应体中包含一个指向下一页的链接(如`next_url`)或者使用页码。 我们以两种常见分页方式为例: 方式1:响应中包含`next_url`字段(如GitHub API的分页方式) 方式2:使用页码参数(page和size)进行分页,总页数由响应中的`total_pages`决定。 这里我们以方式1为例,因为它更通用。 流程: 1. 轮询操作状态,直到状态不为“RUNNING”(例如“SUCCESS”或“COMPLETED”)。 2. 一旦操作完成,获取结果的第一页(初始URL)。 3. 处理当前页的数据。 4. 检查是否有下一页(通过`next_url`字段),如果有,则请求下一页,重复步骤3-4;否则结束。 注意:在轮询操作状态时,我们使用一个循环,每次等待2秒(避免频繁请求)。 假设状态查询接口返回的JSON格式如下: ```json { "status": "RUNNING", "result_url": "http://.../results" // 当操作完成时,这个字段存在并提供获取结果的URL } ``` 或者当操作完成时,状态变为“COMPLETED”,并且我们可以用另一个URL获取结果(可能是分页的)。 具体步骤: 步骤1:轮询操作状态,直到完成 步骤2:获取结果的第一页(初始结果URL) 步骤3:处理分页循环 我们假设获取操作状态的接口为: ${host}/sessions/${SESSIONHANDLE}/operations/${OPERATIONHANDLE}/status 当操作完成后,该接口返回: ```json { "status": "COMPLETED", "result_url": "${host}/sessions/${SESSIONHANDLE}/operations/${OPERATIONHANDLE}/results?page=1" } ``` 然后我们使用这个result_url来获取第一页。 获取结果分页的接口返回格式: ```json { "data": [ ... ], // 当前页的数据数组 "pagination": { "next_url": "http://.../results?page=2", // 可能为null或不存在表示没有下一页 "total_pages": 5 } } ``` 我们使用jq来解析,判断是否有下一页(即next_url不为null且非空)。 脚本结构: 1. 轮询操作状态(使用之前的方法) 2. 获取结果初始URL(从状态完成的响应中提取result_url) 3. 设置一个循环来处理分页: 当前URL不为空时: 用curl获取当前URL的响应 用jq提取当前页的data,并处理(例如保存到文件或输出) 用jq提取下一页的URL(.pagination.next_url),如果为空则退出循环,否则将当前URL设置为下一页URL 注意:在分页获取过程中,同样需要处理错误和超时。 示例代码: 注意:以下代码中,我们假设状态查询接口在操作完成后返回的JSON中包含"result_url"字段。 步骤1:轮询操作状态 ```bash # 先定义host和两个handle host="http://your-api-host" SESSIONHANDLE="your-session-handle" OPERATIONHANDLE="your-operation-handle" # 轮询状态 while true; do # 获取状态 status_response=$(curl -sL --max-time 3600 -H "Accept: application/json" \ "${host}/sessions/${SESSIONHANDLE}/operations/${OPERATIONHANDLE}/status") # 提取状态字段 STATUS=$(echo "$status_response" | jq -r '.status') echo "当前状态: $STATUS" if [ "$STATUS" != "RUNNING" ]; then # 检查是否完成(这里假设非运行状态就是完成,可能是COMPLETED, FAILED等) if [ "$STATUS" == "COMPLETED" ]; then # 提取结果URL result_url=$(echo "$status_response" | jq -r '.result_url') if [ "$result_url" == "null" ] || [ -z "$result_url" ]; then echo "操作完成但没有返回结果URL" exit 1 fi echo "结果初始URL: $result_url" break else echo "操作以状态 $STATUS 结束,未完成" exit 1 fi fi sleep 2 done ``` 步骤2:处理分页 ```bash # 现在有初始结果URL current_url="$result_url" page=1 # 循环处理每一页 while [ -n "$current_url" ] && [ "$current_url" != "null" ]; do echo "获取第 $page 页: $current_url" # 获取当前页数据 page_response=$(curl -sL --max-time 3600 -H "Accept: application/json" "$current_url") # 处理数据:这里我们假设将数据追加到一个文件,使用jq将data数组中的每个元素转换为一行JSON # 注意:如果data是数组,我们可以用jq的'.data[]'来遍历,然后输出为行分隔的JSON echo "$page_response" | jq -c '.data[]' >> results.json # 获取下一页的URL(假设分页信息在.pagination.next_url) next_url=$(echo "$page_response" | jq -r '.pagination.next_url') # 检查next_url是否有效(非null且非空) if [ "$next_url" == "null" ] || [ -z "$next_url" ]; then echo "没有下一页了" break fi current_url="$next_url" page=$((page+1)) done echo "总共获取了 $page 页数据" ``` 完整脚本: 将上述两部分组合起来,并添加必要的错误处理。 注意:如果操作状态是FAILED,我们应该退出而不是获取结果。 另外,分页请求中,我们假设每个分页请求都是GET请求,并且URL是绝对路径(如果API返回的是相对路径,可能需要拼接基础URL,但通常API返回的是绝对URL)。 如果API返回的是相对路径,我们可以使用以下方式拼接: base_domain="http://your-api-host" current_url="${base_domain}${next_url}" 但根据示例,我们假设API返回的是绝对URL。 如果分页信息中不包含next_url,而是包含当前页码和总页数,那么我们可以自己构建URL(需要知道分页参数)。例如: next_page=$((current_page+1)) if [ $next_page -le $total_pages ]; then current_url="http://.../results?page=$next_page" else break fi 但这里我们采用更通用的next_url方式。 请根据实际API响应调整脚本中的jq解析部分。 最后,我们生成相关问题: 1. 如何处理API返回的相对路径分页URL? 2. 当API分页返回的数据量很大时,如何优化内存使用? 3. 在轮询状态时,如何设置超时以避免无限等待? 注意:在脚本中,我们使用了jq,请确保系统已安装jq。 完整脚本示例(假设API返回绝对URL):</think># Shell脚本轮询获取HTTP API操作结果并处理分页数据 下面是一个完整的Shell脚本解决方案,用于轮询HTTP API操作结果并处理分页数据。这个方案结合了轮询机制和分页处理,适用于大多数RESTful API。 ```bash #!/bin/bash # 配置API认证和基础URL API_HOST="https://api.example.com" AUTH_TOKEN="Bearer eyJhbGciOiJIUzUxMiJ9.eyJ1aWQiOiJiYzk4NGZiMS0zYTUzLTQ0YWEtYThiZi1iOTJlN2Y2ZTRjMzEi" SESSION_HANDLE="session123" OPERATION_HANDLE="operation456" # 1. 轮询操作状态直到完成 while true; do # 获取操作状态 STATUS_JSON=$(curl -sL --max-time 10 \ -H "Accept: application/json" \ -H "Authorization: $AUTH_TOKEN" \ "$API_HOST/sessions/$SESSION_HANDLE/operations/$OPERATION_HANDLE/status") # 提取状态字段 STATUS=$(echo "$STATUS_JSON" | jq -r '.status') echo "操作状态: $STATUS" # 检查操作是否完成 if [ "$STATUS" != "RUNNING" ] && [ "$STATUS" != "PENDING" ]; then # 检查操作是否成功完成 if [ "$STATUS" != "COMPLETED" ] && [ "$STATUS" != "SUCCESS" ]; then echo "操作失败: $STATUS" exit 1 fi # 获取结果URL RESULT_URL=$(echo "$STATUS_JSON" | jq -r '.result_url') if [ -z "$RESULT_URL" ] || [ "$RESULT_URL" = "null" ]; then echo "未找到结果URL" exit 1 fi break fi # 等待2秒后重试 sleep 2 done # 2. 处理分页数据 PAGE=1 ALL_RESULTS=() while true; do # 获取当前页数据 echo "获取第 $PAGE 页数据..." PAGE_URL="$RESULT_URL?page=$PAGE&size=100" PAGE_JSON=$(curl -sL --max-time 10 \ -H "Accept: application/json" \ -H "Authorization: $AUTH_TOKEN" \ "$PAGE_URL") # 检查API响应是否有效 if ! echo "$PAGE_JSON" | jq -e . >/dev/null 2>&1; then echo "无效的API响应: $PAGE_JSON" exit 1 fi # 提取当前页数据 CURRENT_PAGE=$(echo "$PAGE_JSON" | jq -r '.page // .current_page') TOTAL_PAGES=$(echo "$PAGE_JSON" | jq -r '.total_pages') PAGE_SIZE=$(echo "$PAGE_JSON" | jq -r '.size // .page_size') # 处理当前页结果 RESULTS=$(echo "$PAGE_JSON" | jq -c '.data[]') while IFS= read -r item; do ALL_RESULTS+=("$item") done <<< "$RESULTS" echo "已获取第 $PAGE/$TOTAL_PAGES 页数据 (${#ALL_RESULTS[@]} 条记录)" # 检查是否还有更多页 if [ "$PAGE" -ge "$TOTAL_PAGES" ] || [ -z "$RESULTS" ]; then break fi # 下一页 PAGE=$((PAGE + 1)) done # 3. 处理所有结果 echo "总共获取数据: ${#ALL_RESULTS[@]} 条" for item in "${ALL_RESULTS[@]}"; do # 这里处理每条数据,例如: id=$(echo "$item" | jq -r '.id') name=$(echo "$item" | jq -r '.name') echo "处理记录: $id - $name" # 添加你的业务逻辑 done # 可选:将结果保存到文件 echo "${ALL_RESULTS[@]}" | jq -s '.' > api_results.json echo "结果已保存到 api_results.json" ``` ## 关键功能说明 1. **轮询操作状态**: - 使用`while`循环持续检查操作状态 - 支持多种状态判断(RUNNING, PENDING, COMPLETED等) - 获取结果URL进行下一步处理 2. **分页数据处理**: - 使用页码参数(`page`和`size`)遍历所有数据页 - 自动检测总页数(`total_pages`)和当前页码 - 收集所有结果到数组中统一处理 3. **数据处理**: - 使用`jq`解析JSON数据 - 支持多种API响应格式(`.data[]`或直接数组) - 可选将结果保存为JSON文件 ## 实际应用场景 1. **批量数据处理**: ```bash # 处理所有结果并导出到CSV echo "id,name,value" > results.csv for item in "${ALL_RESULTS[@]}"; do id=$(echo "$item" | jq -r '.id') name=$(echo "$item" | jq -r '.name') value=$(echo "$item" | jq -r '.value') echo "$id,$name,$value" >> results.csv done ``` 2. **过滤特定数据**: ```bash # 只处理状态为"active"的记录 ACTIVE_RESULTS=() for item in "${ALL_RESULTS[@]}"; do status=$(echo "$item" | jq -r '.status') if [ "$status" = "active" ]; then ACTIVE_RESULTS+=("$item") fi done ``` 3. **并行处理**(使用`xargs`加速): ```bash # 并行处理所有结果 printf '%s\n' "${ALL_RESULTS[@]}" | \ xargs -P 4 -I {} sh -c 'echo {} | jq -r "Processing: \(.id)"' ``` ## 安全增强建议 1. **安全存储认证令牌**: ```bash # 从安全存储读取令牌 AUTH_TOKEN=$(gpg -d auth_token.gpg 2>/dev/null) if [ -z "$AUTH_TOKEN" ]; then echo "无法获取认证令牌" exit 1 fi ``` 2. **添加请求超时和重试**: ```bash # 带重试机制的curl封装函数 curl_with_retry() { local url=$1 local max_retries=3 local retry_count=0 while [ $retry_count -lt $max_retries ]; do response=$(curl -sL --max-time 10 -H "Authorization: $AUTH_TOKEN" "$url") if [ $? -eq 0 ] && jq -e . >/dev/null 2>&1 <<<"$response"; then echo "$response" return 0 fi retry_count=$((retry_count + 1)) sleep $((2 * retry_count)) done echo "API请求失败: $url" return 1 } ``` 此脚本提供了完整的轮询和分页处理解决方案,适用于大多数API场景。您可以根据具体API响应结构调整`jq`查询表达式[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值