Lưu ý khi sử dụng echo khi biến có JSON format
Published: 2024-04-10 02:35:16

Ví dụ tôi đang có biến sau lấy kết quả response của một API:

```
projects=$(curl --insecure -s -X GET "$octopusURL/api/projects/all" -H "accept: application/json" -H "$header")
```
Response có dạng sau:
```
[
  {
    "Id": "string",
    "VariableSetId": "string",
    "DeploymentProcessId": "string",
    "DiscreteChannelRelease": true,
    "IncludedLibraryVariableSetIds": [
      "string"
    ],
    "DefaultToSkipIfAlreadyInstalled": true,
    "TenantedDeploymentMode": "Untenanted",
    "DefaultGuidedFailureMode": "EnvironmentDefault",
    "VersioningStrategy": {
      "DonorPackageStepId": "string",
      "Template": "string"
    },
    "ReleaseCreationStrategy": {
      "ReleaseCreationPackageStepId": "string",
      "ChannelId": "string"
    },
    "Templates": [
      {
        "Id": "string",
        "Name": "string",
        "Label": "string",
        "HelpText": "string",
        "DefaultValue": {
          "IsSensitive": true,
          "Value": "string",
          "SensitiveValue": {
            "HasValue": true,
            "NewValue": "string"
          }
        },
        "DisplaySettings": {
          "additionalProp1": "string",
          "additionalProp2": "string",
          "additionalProp3": "string"
        }
      }
    ],
    "AutoDeployReleaseOverrides": [
      {
        "EnvironmentId": "string",
        "TenantId": "string",
        "ReleaseId": "string"
      }
    ],
    "Name": "string",
    "Slug": "string",
    "Description": "string",
    "IsDisabled": true,
    "ProjectGroupId": "string",
    "LifecycleId": "string",
    "AutoCreateRelease": true,
    "ProjectConnectivityPolicy": {
      "SkipMachineBehavior": "None",
      "TargetRoles": [
        "string"
      ],
      "AllowDeploymentsToNoTargets": true
    },
    "LastModifiedOn": "2024-04-10T02:18:59.115Z",
    "LastModifiedBy": "string",
    "Links": {
      "additionalProp1": "string",
      "additionalProp2": "string",
      "additionalProp3": "string"
    }
  }
]
```


Nếu tôi muốn lấy project ID của một project Name tương ứng, thường sẽ sử dụng như sau:

```
projectId=$(echo "$projects" | jq --arg projectName "$projectName" -r '.[] | select(.Name == $projectName) | .Id')
```

Và sau đó rất nhiều điều rắc rối, lỗi xuất hiện:

```
parse error: Invalid string: control characters from U+0000 through U+001F must be escaped at line 268, column 76
```
sửa lỗi này thì thêm 
`tr -d '\000-\037'` vào command để loại bỏ việc xuống hàng trong một chuỗi của value

Nhưng lại tiếp tục xảy ra

```
parse error: Invalid escape at line 1, column 17150
```

Khi tìm hiểu thì thấy:
"DefaultValue": "C:\Web\xxxxx\xxxx",
Tức là bị lỗi khi có ký tự `\` trong value

Vậy là tiến hành replace ký tự đó v.v... 

Nhưng lỗi vẫn cứ tiếp tục...

Nguyên nhân là do lệnh `echo` đã tự động thay đổi:
- `\n` -> new line
- `\\` -> `\`
- `\"` -> `"`

Để tránh việc này, thay vì dùng echo, ta có thể lưu response thành file .txt và sử dụng lệnh `cat`

```
curl --insecure -s -X GET "$octopusURL/api/projects/all" -H "accept: application/json" -H "$header" > /tmp/projects.json
projectId=$(cat /tmp/projects.json | jq '.[] | select(.Name=="$projectName") | .Id')
echo "The projectId for $projectName is $projectId"
rm /tmp/projects.json
```

Hoàn toàn không xảy ra lỗi vớ vẫn nào nữa...