다음 스크립트가 있고 빈 텍스트 파일을 만들려고 합니다. 시도하고 touch
또 시도했지만 echo -n >
실패했습니다.
#!/bin/bash
set filename_result="contents"
echo "filename=$filename_result" # Shows: filename=
rm -f "$filename_result".json
touch $filename_result # Error: usage: touch [-A [-][[hh]mm]SS] [-acfhm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...
# Note that `% touch myfile` works fine on the command line
touch -- "$filename_result" # Error: touch: : No such file or directory
echo -n > "$filename_result" # Error: No such file or directory
echo "[" >> "$filename_result"
for file in *json
do
echo "examining file: $file"
echo "\n" >> "$filename_result"
cat $file >> "$filename_result"
echo "\n" >> "$filename_result"
done
echo "\n]" >> "$filename_result"
mv $filename_result "$filename_result".json
편집: 화면 filename_result
변수에 인쇄하면 설정 후 비어 있음이 표시됩니까?
echo "filename=$filename_result" # Shows: filename=
답변1
set filename_result="contents"
할당된 값이 없습니다 filename_result
. 첫 번째 위치 매개변수에 할당되며 값 자체는 입니다 filename_result=contents
. 예:
$ set filename_result="contents"
$ echo "$1"
filename_result=contents
변수가 filename_result
존재하지 않으며 $filename_result
비어 있는 상태로 확장됩니다. "$filename_result"
이는 와 동일합니다 ""
.
set filename_result="contents"
딱 원하는 것 보다는
filename_result="contents"
답변2
이 시도:
filename_result=contents
touch -- "$filename_result"
또는:
set contents
touch -- "$1"
답변3
여러 JSON 파일의 콘텐츠를 요소로 포함하는 JSON 배열을 생성하려는 것 같습니다. 각 파일의 내용 사이에 쉼표 삽입을 생략한 것을 확인했습니다. 이로 인해 잘못된 JSON이 발생합니다.
대신 스크립트를 다음 명령으로 바꿀 수 있습니다.
jq -s . ./*.json >outfile
그러면 현재 디렉터리에서 이름이 일치하는 모든 파일을 읽고 *.json
각 파일에 대한 JSON 문서를 하나의 요소로 사용하여 배열을 만듭니다. 출력이 기록됩니다 outfile
.
jq
대부분의 Unices에서 작동하는 명령줄 JSON 파서입니다(패키지 관리자를 확인하세요). -s
(또는) 옵션은 --slurp
방금 설명한 것과 정확히 일치합니다(배열로 읽기).
이것은 .
"ID 필터"이며 그 역할은 데이터만 전달하는 것입니다.
귀하의 코드와 관련하여 :
변수를 설정하려는 시도 를 제외하고 set
(이것은Kamil Machorovsky는 다음과 같이 지적했습니다.csh
이미 이것이 쉘에서 수행되는 방식입니다 tcsh
. 일부 명령(특히 루프 내부 명령)을 함께 그룹화하여 출력을 단순화할 수 있습니다. touch
존재하지 않는 파일로 리디렉션하면 파일이 생성되므로 필요 하지 않습니다 .
다음은 문제에 대한 내 자신의 견해입니다. 각 파일의 내용 사이에 누락된 쉼표도 삽입됩니다.
#!/bin/sh
outfile=outfile
# Will truncate (empty) the file if it exists,
# or create it if it doesn't.
echo '[' >"$outfile"
# Get a list of all JSON files into the list
# of positional parameters.
set -- ./*.json
# Loop over all but the last file.
# Output each file and a comma.
while [ "$#" -gt 1 ]; do
# The "current" file that we're working on is "$1",
# the first one in the list.
cat "$1"
echo ,
shift # shifts this file off the list
done >>"$outfile
# The last file should not have comma after it.
{
cat "$1"
echo ']'
} >>"$outfile"
이 while
루프는 위치 인수 목록(목록은 를 사용하여 생성됨 set
)의 JSON 파일을 반복합니다. 각 파일 뒤에 쉼표를 붙여서 출력하고 싶지만, 마지막 파일 뒤에 쉼표가 오면 안 되기 때문에 별도로 처리합니다(이렇게 하면 JSON 형식이 손상됩니다). 따라서 루프는 목록의 마지막 파일( $#
위치 인수 목록의 길이)을 제외한 모든 파일을 제거할 때까지 반복됩니다.
{ ...; }
마지막 파일이 마지막 파일에 의해 처리됩니다. 중괄호 안에 명령 세트를 그룹화하면 단일 리디렉션을 통해 이러한 모든 명령의 출력을 한 번에 리디렉션할 수 있습니다. 마찬가지로 루프의 출력은 단일 리디렉션을 통해 리디렉션될 수 있습니다.
같은 방법이지만 GNU를 사용합니다 awk
.
awk 'BEGIN { print "[" }
{ print }
ENDFILE { if (FILENAME != ARGV[ARGC-1]) print "," }
END { print "]" }' *.json
GNU에는 표준 및 블록(여기서는 출력 배열의 초기 및 최종 구분 기호 로 사용됨) awk
외에 및 블록이 있습니다. 이는 (놀랍지도 않게) 각 개별 입력 파일이 처리되기 전후에 트리거됩니다. 여기서는 출력의 각 파일 내용 사이에 쉼표를 사용합니다(마지막 파일 다음은 제외).BEGIN
END
[
]
BEGINFILE
ENDFILE
ENDFILE
이 { print }
블록은 수정 없이 각 파일의 모든 줄을 전달합니다.
FILENAME
, ARGV
및 는 GNU가 자동으로 현재 파일 이름, 스크립트에 제공된 인수 목록(이 경우 파일 이름) 및 파일 이름 수로 자동으로 채우는 변수입니다 ARGC
.awk