피시 (유닉스 셸)

피시(fish)는 상호작용과 사용성에 초점을 둔 유닉스 셸이다. 피시는 구성보다는 사용자 기능들을 기본으로 제공하도록 설계되었다. 피시는 이국적인 유닉스 셸로 간주되는데, POSIX 셸 표준을 철저히 준수하지 않기 때문이다.

기능
fish는 사용자가 명령어를 입력할 때마다 명령어 기록과 현재 디렉터리에 기반하여 증분 제안을 표시한다. 이는 배시의 기록 검색과 유사하게 작동하지만, 항상 켜져 있어 명령어를 입력하는 동안 사용자에게 지속적인 피드백을 제공한다. fish는 또한 파일 경로 확장(와일드카드 및 중괄호 확장 지원), 환경 변수, 명령어별 완성을 지원하는 기능이 풍부한 탭 완성 기능을 포함한다. 설명이 포함된 옵션을 포함하여 명령어별 완성은 해당 명령어의 Man page에서 어느 정도 생성될 수 있지만, 소프트웨어에 포함되거나 셸 사용자가 직접 작성한 사용자 정의 완성 기능도 포함될 수 있다.

fish의 제작자는 새로운 기능을 구문보다는 명령어로 추가하는 것을 선호했다. 이는 내장된 기능을 통해 옵션과 도움말 텍스트가 있는 명령어를 검색할 수 있게 함으로써 기능의 발견 가능성을 높였다. 함수에도 사람이 읽을 수 있는 설명을 포함할 수 있다. 특수 help 명령어를 사용하면 사용자의 웹 브라우저에서 모든 fish 문서에 접근할 수 있다.

구문
구문은 POSIX 호환 셸(예: 배시)과 유사하지만 여러 면에서 차이가 있다.

# 변수 할당
#
# 변수 'foo'의 값을 'bar'로 설정한다.
# fish는 공백에 민감한 = 연산자를 사용하지 않는다.
# 'set' 명령어는 배열, 유효 범위(scoping) 등으로 확장되어 작동한다.

> set foo bar
> echo $foo
bar

# 명령어 치환
#
# 'pwd' 명령어의 출력을 변수 'wd'에 할당한다.
# fish는 중첩이 불가능하고 작은따옴표(' ')와 혼동될 수 있는 백틱(``)을 사용하지 않는다.

> set wd (pwd)
> set wd $(pwd) # 버전 3.4부터 지원
> echo $wd
~

# 배열 변수. 'A'는 5개의 값을 가진 배열이 된다.
> set A 3 5 7 9 12
# 배열 슬라이싱. 'B'는 'A'의 처음 두 요소가 된다.
> set B $A[1 2]
> echo $B
3 5
# 다른 배열이나 심지어 명령어 치환 출력으로
# 인덱싱할 수 있다.
> echo $A[(seq 3)]
3 5 7
# 'A'의 세 번째와 다섯 번째 요소를 삭제한다.
> set --erase A[$B]
> echo $A
3 5 9

# for 루프, jpeg를 png로 변환
> for i in *.jpg
 convert $i (basename $i .jpg).png
 end

# fish는 다중 행 기록과 편집을 지원한다.
# 세미콜론은 줄바꿈처럼 작동한다.
> for i in *.jpg; convert $i (basename $i .jpg).png; end

# while 루프, /etc/passwd의 행을 읽어 파일에서 콜론으로 구분된
# 다섯 번째 필드를 출력한다. 이는 사용자 설명이어야 한다.
> while read line
 set arr (echo $line|tr : \n)
 echo $arr[5]
 end < /etc/passwd

# 문자열 교체 (모든 i를 I로 교체)
> string replace -a "i" "I" "Wikipedia"
WIkIpedIa

 암시적 서브셸 없음 
파이프라인, 함수, 루프와 같은 일부 언어 구조는 다른 셸 언어에서 이른바 서브셸을 사용하여 구현되어 왔다. 서브셸은 작업을 수행하기 위해 몇 가지 명령어를 실행한 다음 부모 셸로 돌아가는 자식 프로그램이다. 이러한 구현 방식은 일반적으로 변수 할당과 같이 서브셸에서 이루어진 상태 변경이 메인 셸로 전파되지 않는 부작용을 갖는다. fish는 언어 기능을 위해 서브셸을 생성하지 않으며, 모든 내장 기능은 부모 셸 내에서 발생한다.
# 'read' 내장 명령어가 자체 서브셸에서 실행되므로 많은 다른 셸에서는 작동하지 않는다.
# 배시에서 파이프의 오른쪽은 어떠한 부작용도 가질 수 없다.
# ksh에서는 아래 명령어가 작동하지만 왼쪽이 부작용을 가질 수 없다.
# fish와 zsh에서는 양쪽 모두 부작용을 가질 수 있다.
> cat *.txt | read line

 변수 할당 예시 
이 배시 예시는 보이는 대로 작동하지 않는다. 루프 본문이 서브셸이므로 $found에 대한 업데이트가 유지되지 않기 때문이다.
found=
cat /etc/fstab | while read dev mnt rest; do
 if test "$mnt" = "/"; then
 found="$dev"
 fi
done

해결책:
found=
while read dev mnt rest; do
 if test "$mnt" = "/"; then
 found="$dev"
 fi
done < /etc/fstab

Fish 예시:
set found
cat /etc/fstab | while read dev mnt rest
 if test "$mnt" = "/"
 set found $dev
 end
end

유니버설 변수
fish에는 유니버설 변수(universal variables)라는 기능이 있어, 사용자가 실행 중인 모든 fish 셸에서 변수에 값을 영구적으로 할당할 수 있다. 변수 값은 로그아웃과 재부팅 후에도 기억되며, 변경 사항은 즉시 모든 실행 중인 셸로 전파된다.
# emacs를 기본 텍스트 편집기로 설정한다. '--universal' (또는 '-U')은 fish에게
# 이것을 유니버설 변수로 만들라고 지시한다.
> set --universal EDITOR emacs

# 이 명령어는 실행 중인 모든 fish 인스턴스에서 fish 프롬프트의
# 현재 작업 디렉터리 부분을 파란색으로 만든다.
> set --universal fish_color_cwd blue

기타 기능
 고급 탭 완성 (사용자 정의 완성 작성 지원 포함).
 광범위한 오류 검사를 포함한 구문 강조.
 X 클립보드 지원.
 Terminfo에 기반한 스마트한 단말기 처리.
 검색 가능한 명령어 기록.
 웹 기반 설정 (fish_config).

배시/fish 변환 표

 같이 보기 
 유닉스
 유닉스 셸

 각주 

 외부 링크 
 – containing documentation and downloads
 fish on GitHub (active)
 fish on Gitorious (obsolete)
 fish on SourceForge (obsolete)
 Fish-users – general discussion list for fish users
 Shell Translation Dictionary - another Bash/Fish translation table

분류:유닉스 셸
분류:스크립트 언어
분류:C로 작성된 자유 소프트웨어