Bash 리디렉션이 SQLite 명령에서 작동하지 않습니다.

Bash 리디렉션이 SQLite 명령에서 작동하지 않습니다.

Bash는 이런 방식으로 다른 명령을 표준 입력으로 연결할 수 있습니다.

$ ls /bin/aud* | cat
/bin/audacity
/bin/audiocompose
/bin/audiosend
...

...그리고 이 방법으로:

$ cat <(ls /bin/aud*)
/bin/audacity
/bin/audiocompose
/bin/audiosend
...

그러나 동일한 패턴을 사용하여 SQLite에 쿼리를 보내려고 하면 첫 번째 양식에서 다음과 같은 결과가 나타납니다.

$ echo "select count(*) from urls;" | \
    sqlite3 ~/.config/google-chrome/Default/History
5983

...하지만 두 번째 오류는 다음과 같습니다.

$ sqlite3 ~/.config/google-chrome/Default/History \
   <(echo "select count(*) from urls;")
Error: near "/": syntax error

이것은 놀라운 일입니다... SQL 문은 쉘에 의해 삽입되거나 엉망이 되지 않습니다.

$ echo "select count(*) from urls;"
echo "select count(*) from urls;"

이는 둘 중 하나와 관련이 없습니다 echo. 확실히 리디렉션에 사용될 수 있습니다.

$ cat <(echo Foo)
Foo

내가 생각할 수 있는 것은 데이터베이스 파일의 경로가 어떻게든 잘못 해석되어 SQL 문으로 전달되었다는 것입니다. ("/"가 포함된 유일한 장소입니다. "/ 근처의 구문 오류에 대한 유일한 설명입니다." .

그런데 왜? 어떤 아이디어가 있나요?

답변1

I/O 리디렉션의 두 번째 형식( <(cmd))은 cmd | other-cmd첫 번째 형식( )과 다르게 동작합니다.

첫 번째는 의 출력을 cmd의 입력에 연결 other-cmd하지만 두 번째는 경로 /dev/fd또는명명된 파이프명령의 경로입니다. 의 표준 출력은 해당 파이프의 다른 쪽 끝에 바인딩되지만 이는 표준 입력 또는 파일 경로에서 읽는 명령과 동일합니다 cmd. 동작은 그런 방식이 아니므로 두 가지 형태의 I/O 리디렉션 간의 차이점을 드러냅니다.catsqlite3

sqlite3 예상하다데이터베이스 경로 뒤에는 선택적 SQL 문이 있으므로 이 대체 경로를 SQL로 구문 분석하려고 시도하지만 실패합니다.

그건 그렇고, 이는 I/O 리디렉션이 전혀 필요하지 않음을 의미합니다. 이 명령은 시도한 어떤 형식보다 원하는 작업을 더 효율적으로 수행합니다.

$ sqlite3 ~/.config/google-chrome/Default/History "select count(*) from urls"

sqlite3단일 SQL 문을 명령줄 매개 변수로 전달할 때는 세미콜론으로 끝나는 문이 필요하지 않습니다.

답변2

$ echo <(echo "hi")
/dev/fd/63

/dev/fd/63SQL이 아니므로 sqlite3표시된 오류 메시지와 함께 실패합니다. cat대조적으로, 파일 읽기(또는 표준 입력 읽기)에는 매우 좋습니다. 생성된 명명된 파이프 또는 /dev/fd파일 <(list)은 표준 입력이 아닙니다.

관련 정보