피시 (유닉스 셸)

피시(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 변환 표
 기능  배시 구문  fish 구문  비고 변수 확장:단어 분할 및 글로브 해석 포함  $var
또는
 ${var[@]}
또는
 ${var[*]}   POSIX 호환 셸 언어에서 버그의 주요 원인으로 식별됨 변수 확장:스칼라  "$var"   모든 변수는 배열임 변수 확장:배열  "${var[@]}" $var 단어 분할 및 글로브 해석을 억제하기 위해 따옴표를 사용할 필요가 없음. 대신 따옴표는 직렬화를 의미함. 변수 확장:공백으로 구분된 문자열로  "${var[*]}" "$var" 텍스트 편집기에서 줄 편집  ,    호출 시 입력 중인 줄을 텍스트 편집기로 이동함 줄 입력 평가      줄 편집기에서 표현식을 즉석에서 평가함 기록 완성      기록 치환  !!    발견 가능하지 않음 명시적 서브셸  (expression) fish -c expression 명령어 치환  "$(expression)""$(expression)" 또는 (expression | string collect) 프로세스 치환  <(expression) (expression | psub) 구문이 아닌 명령어임 논리 연산자  !cmd && echo FAIL || echo OK not command
and echo FAIL
or echo OK 변수 할당  var=valueset var value 문자열 처리:교체  "${HOME/alice/bob}" string replace alice bob $HOME 문자열 처리:접두사 또는 접미사 패턴 제거, 비탐욕적 또는 탐욕적 var=a.b.c
"${var#*.}"  #b.c
"${var##*.}" #c
"${var%.*}"  #a.b
"${var%%.*}" #astring replace --regex '.*?\.(.*)' '$1' a.b.c #b.c
string replace --regex '.*\.(.*)' '$1' a.b.c  #c
string replace --regex '(.*)\..*' '$1' a.b.c  #a.b
string replace --regex '(.*?)\..*' '$1' a.b.c #a 변수 내보내기 (export)  export var set --export var 탭 완성을 통해 옵션 발견 가능 함수 로컬 변수  local var  범위 로컬 변수   set --local var 변수 제거  unset var set --erase var 변수 존재 여부 확인  test -v var set --query var 배열 초기화  var=( a b c )set var a b c 모든 변수는 배열임 배열 반복  for i in "${var[@]}"; do
  echo "$i"
done  for i in $var
  echo $i
end 인자 벡터:모든 인자  "$@" $argv 인자 벡터:인덱싱  "$1" $argv[1] 인자 벡터:길이  $# (count $argv) 인자 벡터:shift shiftset --erase argv[1] 환경 변수 내의 배열 표현  PATH="$PATH:$HOME/.local/bin"  set PATH $PATH $HOME/.local/bin  fish는 변수를 환경으로 전달하거나 환경에서 가져올 때 콜론을 배열 구분자로 간주한다. 이는 $PATH 및 $LS_COLORS와 같은 많은 배열 형태의 환경 변수와 일치한다. 내보내기 및 실행  LANG=C.UTF-8 python3 env LANG=C.UTF-8 python3 env LANG=C.UTF-8 python3는 env가 독립 프로그램이므로 모든 셸에서 작동한다. 산술 연산  $((10/3)) math '10/3' expr 10 / 3은 expr이 독립 프로그램이므로 모든 셸에서 작동한다. 이스케이프 시퀀스  $'\e'  \e printf '\e'는 두 셸 모두에서 작동한다. 두 셸의 printf 내장 명령어는 모두 GNU printf 독립 프로그램과 호환된다. 작은따옴표 문자열:이스케이프 시퀀스  'mom'\s final backslash: \'  'mom\'s final backslash: \\'  배시는 작은따옴표 문자열에서 작은따옴표 자체만 교체하면 되지만, 교체 문자열의 길이는 4자이다. fish에서도 동일한 교체가 작동하지만, 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로 작성된 자유 소프트웨어