当jq输出空字符串时,bash readarray -t数组分配出现问题

如何解决当jq输出空字符串时,bash readarray -t数组分配出现问题

首先-一个非常简单的代码

#!/bin/bash

a_string="string"
readarray -t a <<<"$a_string"
echo "${a[@]}"
echo "${#a[@]}"

# read empty string into array
emptystring=""
readarray -t b <<<"$emptystring"
echo "${b[@]}"
echo "${#b[@]}"

# and Now - empty array
c=()
echo "${c[@]}"
echo "${#c[@]}"

输出

string
1

1

0

因此,使用readarray -t一个空字符串读入bash数组将显示数组长度为1。只有真正的空数组的长度为0。

我的问题-为什么会发生?

以我为例-这是脚本的一部分-执行API调用获取JSON并应用jq过滤器:

URL_list_json=$(curl -s --request GET "$curl_request" --header "Authorization: Bearer ${token}")
readarray -t URL_names <<<"$(echo "$URL_list_json" | jq -r '.[].Body.monitors[].name')"

这是JSON的示例,它会导致jq调用中出现一个空数组:

[
    {
        "Header": {
            "Region": "dc1","Tenant": "tenant1","Stage": "test"
        },"Body": {
            "monitors": []
        }
    }
]

这是具有填充内容的JSON,它从jq调用返回一个非空数组:

[
    {
        "Header": {
            "Region": "dc2","Tenant": "tenant2","Stage": "qa"
        },"Body": {
            "monitors": [
                {
                    "enabled": true,"entityId": "TEST-674BA97E74FC74AA","name": "production.example.com"
                },{
                    "enabled": false,"entityId": "TEST-3E2D23438A973D1E","name": "test.example.com"
                }
            ]
        }
    }
]

我需要检查URL_names数组是否为空。如果不为空,则遍历内容。如果为空-表示jq没有返回任何结果-白色以记录并继续。

如果我使用if ((${#URL_names[@]}))作为检查数组是否为空的方法,即使该数组仅来自jq调用中的空字符串,它也将返回1,因此此逻辑将失败。

有什么其他方法可以处理上述情况?

我可以将jq过滤器的输出分配给一个字符串,然后使用 if 语句检查该字符串是否为空以及是否为非空,然后将该字符串分配给数组,但这引入了其他元素。通过这种方法,我可以完全跳过使用数组-我希望仅使用数组来完成此任务。

谢谢

解决方法

为什么会这样?

因为它读一行。来自bash manual here document

[n]

[...]结果以单个字符串的形式提供,在其标准输入(或如果指定n的情况下为文件描述符n)中以附加换行符的形式提供给命令。

因为有换行符,所以public class MainActivity extends AppCompatActivity { ImageView videoImage ; EditText editTextVideoTitle; EditText editTextVideoDescription; Button btnPostButton; Button btnCancelButton; private String mVideoPath; private String mVideoThumb; String strVideoTitle; String strVideoDescription; boolean videoPosted; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_post_vid_with_desc); editTextVideoTitle = (EditText) findViewById(R.id.videoTitle); editTextVideoDescription = (EditText) findViewById(R.id.videoDescription); btnPostButton = (Button) findViewById(R.id.postButton); btnCancelButton = (Button) findViewById(R.id.cancelButton);; mVideoPath = getIntent().getStringExtra("path"); mVideoThumb = getIntent().getStringExtra("thumb"); btnPostButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { videoPosted = postVideo(); if (videoPosted) { Toast.makeText(getApplicationContext(),"Your video posted successfully.",Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(),"Error in posting video,please try again.",Toast.LENGTH_SHORT).show(); } } }); } public boolean postVideo() { Log.i("Info","PostVidWithDescActivity : postVideo : Start"); String strUserId = ""; String strReservedfield = ""; boolean isVideoPosted = false; sharedPreferences = this.getSharedPreferences("com.app.rapid",Context.MODE_PRIVATE); strVideoTitle = editTextVideoTitle.getText().toString(); strVideoDescription = editTextVideoDescription.getText().toString(); try { strUserId = sharedPreferences.getString("userId",""); strReservedfield = "ReservedField"; outputData = new PostToServerAsyncTask().execute(mVideoPath,strUserId,strVideoTitle,strVideoDescription,strReservedfield).get(); } catch (ExecutionException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); }catch (Exception e) { e.printStackTrace(); } if (null != outputData && outputData.equalsIgnoreCase("200")) { isVideoPosted = true; } else{ isVideoPosted = false; } return isVideoPosted; } private class PostToServerAsyncTask extends AsyncTask<String,Void,String> { private String content; private String Error = null; private int serverResponseCode; Context context; ProgressDialog progressDialog; @Override protected void onPreExecute() { super.onPreExecute(); Log.i("inputBuilder","PostToServerAsyncTask : onPreExecute Start") ; progressDialog = new ProgressDialog(MainActivity.this); progressDialog.setMessage("Loading..."); progressDialog.setIndeterminate(false); //progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); progressDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.YELLOW)); progressDialog.setCancelable(false); progressDialog.show(); Log.i("inputBuilder","PostToServerAsyncTask : onPreExecute End") ; } @Override protected String doInBackground(String... inputData) { /* File upload code */ try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } return "Some string"; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); Log.i("inputBuilder","PostToServerAsyncTask : onPostExecute Start") ; if (null != progressDialog && progressDialog.isShowing()) { progressDialog.dismiss(); } Log.i("inputBuilder","PostToServerAsyncTask : onPostExecute End") ; } } } 读取一个空行。您可以这样做:

readarray

注意:

  • readarray -t b < <(printf "%s" "$emptystring") 不是首选。在posix shell中执行echo "$var",在bash中执行printf "%s" "$var"(并且您不必担心多余的换行符)。
  • <<<"$var"总是看起来很奇怪-<<<"$(...)"无论如何都必须分配一个子shell。做<<<
  • 您要执行的操作:< <(...)
  • 如果要检查数组是否为空,请在readarray -t URL_names < <(<<<"$URL_list_json" jq -r '.[].Body.monitors[].name')中进行检查。 I see ex. jq,然后检查退出状态。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?