Bash문법

> 출력 리다이렉션.
명령 실행의 표준 출력(stdout)을 파일로 저장합니다.
유닉스 계열 운영체제는 장치도 파일로 처리하기 때문에 명령 실행결과를 특정 장치로 보낼 수도 있습니다.
$ echo "hello" > ./hello.txt
$ echo "hello" > /dev/null
< 입력 리다이렉션.
파일의 내용을 읽어 명령의 표준입력(stdin)으로 사용합니다.
$ cat < ./hello.txt
>> 명령 실행의 표준 출력(stdout)을 파일에 추가합니다.
>는 이미 있는 파일에 덮어쓰지만 >> 는 파일 뒷부분에 내용을 추가합니다.
$ echo "world" >> ./hello.txt
2> 명령실행의 표준 에러(stderr)를 파일로 저장합니다.
2>> 명령실행의 표준에러(stderr)를 파일에 추가합니다.
&> 표준 출력과 표준에러를 모두 파일로 저장합니다.
1>&2 표준출력을 표준에러로 보냅니다.
echo명령으로 문자열을 표준출력으로 출력했지만 표준에러로 보냈기 때문에 변수에는 문자열이 들어가지 않습니다.
$ hello=$(echo "hello world" 1>&2)
$ echo $hello
2>&1 표준 에러를 표준 출력으로 보냅니다.
abcd 라는 명령은 없으므로 에러가 발생하지만 에러를 표준출력으로 보낸 뒤 다시 /dev/null로 보냈기 때문에 아무것도 출력되지 않습니다.
$ abcd > /dev/null 2>&1
| 파이프.
명령실행의 표준 출력을 다른 명령의 표준 입력으로 보냅니다.
즉 첫번째 명령의 출력값을 두 번째 명령에서 처리합니다.
$ ls -al | grep .txt
$ Bash의 변수입니다.
값을 저장할때는 $를 붙이지 않고, 변수를 가져다 쓸 때만 $를 붙입니다.
$ hello="Hello world"
$ echo $hello
Hello world  
&() 명령 실행 결과를 변수화합니다.
명령 실행 결과를 변수에 저장하거나 다른 명령의 매개변수로 넘겨줄 때 사용합니다.
또는 문자열 안에 명령의 실행결과를 넣을 때 사용합니다.
`` &()과 마찬가지로 명령실행 결과를 변수화합니다.
$ sudo docker rm `docker ps -aq`
$ echo `date`
2024년 12월 1일 일요일 11시 30분 31초 KST
&& 한 줄에서 명령을 여러 개 실행합니다.
단 앞에있는 명령이 에러없이 실행되어야 뒤에 오는 명령이 실행됩니다.
$ make && make install
; 한 줄에서 명령을 여러 개 실행합니다.
앞에있는 명령이 실패해도 뒤에 오는 명령이 실행됩니다.
$ false; echo "hello"
hello
' ' 문자열입니다.
' ' 안에 들어있는 변수는 처리되지 않고 변수명 그대로 사용됩니다.
또한 "와 $()도 처리되지 않고 그대로 사용됩니다.
$ echo '$USER'
USER
" " 문자열입니다.
명령어 안에 매개 변수를 입력하거나 변수에 저장할 때 주로 사용합니다. 
' '와 달리 " " 안에 변수가 들어있으면 변수의 내용으로 바뀝니다.
또한 " 와 $()도 실행 결과 값이 사용됩니다.
$ echo "Hello World"
Hello World
$ echo "$USER"
root
$ echo "Host name is $(hostname)"
Host name is Sunui-MacBookPro.local
$ echo "Time : `date`"
Time : 2024년 12월  1일 일요일 11시 39분 16초 KST
" ' ' " " " 안에 ' ' 가 들어갈 수 있습니다.
명령 안에서 다시 명령을 실행하고 매개 변수를 지정할 때 사용합니다.
$ bash -c "/bin/echo Hello 'World'"
Hello World
\"
\$hello
' '안에서 "를 사용할 때는 \" 처럼 앞에 \ 를 붙여줍니다.
$ bash -c "/bin/echo '{ \"user\" : \"$USER\" }'"
{ "user" : "root" }
" "안에서 ", $ , ` 등의 특수문자를 그대로 사용하려면 앞에 \ 를 붙여줍니다.
$ echo "\$hello \" \`"
$hello " `
${} 변수 치환(substitution)입니다.
" " 문자열 안에서 변수를 출력할 때 주로 사용합니다.
${} 대신 $만 사용해도 됩니다.
$ str="World"
$ echo "Hello ${str}"
Hello World
스크립트에서 변수의 기본 값을 설정할 때도 사용합니다.
다음은 HELLO변수가 있으면 그대로 사용하고 변수가 없으면 기본 값으로 설정한 abcd를 대입합니다.
$ HELLO=
$ HELLO=${HELLO-"abcd"}
$ echo $HELLO
값이 null인 HELLO 변수가 이미 있기 때문에 기본 값을 대입하지 않습니다.
다음은 변수에 값이 있으면 그대로 사용하고, 값이 null 이면 기본 값으로 설정한 abcd를 대입합니다.
$ world=
$ world=${world:-"abcd"}
$ echo $world
abcd
변수에 값이 null 이므로 기본값을 대입합니다.
\ 한 줄로 된 명령을 여루 줄로 표현할 때 사용합니다.
$ sudo docker run -d --name hello busybox:lastest
$sudo docker run \
> -d \
> --name hello \
> busybox:latest
{1..10} 연속된 숫자를 표현합니다.
{시작숫자..끝숫자}형식입니다.
$ echo {1..10}
1 2 3 4 5 6 7 8 9 10
{문자열1,문자열2} {}안에 문자열을 여러 개 지정하여 명령 실행 횟수를 줄입니다.
다음은 hello.txt, world.txt 두 파일을 한번에 hello-dir디렉터리 아래에 복사합니다.
$ cp ./{hello.txt,world.txt} hello-dir/
if if 조겅문입니다.
변수와 변수끼리 또는 문자열과 비교할 때 사용합니다.
 if [ $a -eq $b]; then
> echo $a
> fi
숫자 비교
-eq : 같다
-ne : 같지 않다
-gt : 초과
-lt : 미만
-le : 이하
문자비교
=, == : 같다
!= : 같지 않다
-z : 문자열이 null 일때
-n : 문자열이 Null 이 아닐 때
for for 반목분입니다. 
변수 안에 있는 값을 반복하거나 범위를 지정하여 반복할 수 있습니다.
NUM={1 2 3}
for i in ${NUM[@]}
do
echo $i
done
while while 반복문입니다.
while : 
do
echo "Hello World";
sleep 1;

done
 <<< 문자열을 명령(브로세스)의 표준 입력으로 보냅니다.
$ cat <<< "User name is $USER"
User name is root
<<EOF
EOF
여러 줄의 문자열을 명령(프로세스)의 표준입력으로 보냅니다.
cat > ./hello.txt <<EOF
Hello World
Host name is $(hostname)
User nane is $USER
EOF
cat 은 파일이나 표준 입력의 내용을 출력하는 명령입니다.
cat의 표준 출력을 ./hello.txt로 저장하고, <<EOF로 문자열을 cat의 표준 입력으로 보냅니다.
이렇게 하면 문자열 3줄이 ./hello.txt파일에 저장됩니다.
export 설정한 값을 환경 변수로 만듭니다.
export <변수>=<값> 형식입니다.
$ export HELLO=world
printf 지정한 형식대로 값을 출력합니다.
파이프와 연동하여 명령(프로세스)에 값을 입력하는 효과를 낼 수 있습니다.
$ printf 80\\nexampleuser\\ny | example-config
예를들어 example-config는 post, user, save configration을 사용자에게 입력받습니다.
printf로 미리 값을 설정하여 파이프로 example-config에 넘겨주면 사용자가 입력하지 않아도 자동으로 값이 입력됩니다.
줄바꿈은 \\n으로 표현합니다.
sed 텍스트 파일에서 문자열을 변경합니다.
hello.txt파일의 내용 중에서 hello라는 문자열을 찾아서 world문자열로 바꾸려면 다음과 같이 실행합니다.
$ sed -i "s/hello/world/g" hello.txt
sed -i "s/<찾을 문자열><바꿀 문자열>/g" <파일명> 형식입니다. 
/와 같은 특수문자는 앞에 \를 붙여 \/로 입력합니다.
# 주석입니다.
스크립트에 설명을 추가하거나, 명령이 실행되지 않도록 합니다.
# echo "Hello world"
  • var
    1. var 키워드 사용 
    var name = 'name';
    2. 명시적으로 변수의 타입을 지정
    String name = 'name';

  • Dynamic Type 여러가지 타입을 가질 수 있는 변수에 쓰는 키워드
    어떤 타입이 올지 모르는 변수에 사용

    처음에 지정한 타입이 바뀔 수 있음

     1. 변수 선언시 타입을 지정하지 X
    var name;
    2. 변수의 타입을 명시
    dynamic name;

    name = 'name';

    name = 'suna';

  • Null Safety dart에서는 어떤 변수가 null 이 될 수 있음을 정확히 표기해야 한다.
    1. ? 사용
    String? name = 'name';
    name = null;
    name?.isNotEmpty;

  • late
    final이나 var 앞에 붙여줄 수 있는 수식어로 재할당을 하지 못하는 변수를 만들어줌.
    런타임 중에 만들어질 수 있음.
    어떤 데이터가 들어올 지 모를 때 사용
    late final String name;
    name = 'name';

  • final
    수정 불가
    final name = 'name'

  • const
    compile-time constant를 만들어줌
    컴파일 할 때 값을 알고있는 변수를 만드는 타입
    수정 불가
    const API = "123456789";

1.dart는 왜 빠를까?

1. dart는 두 개의 컴파일러를 도입하였다.

Dart Native = dart 코드를 여러 cpu의 아키텍쳐(ARM32 & ARM64 & Risc-V & x86_64)에 맞게 변환시키는 컴파일러

Dart Web = dart로 쓴 코드를 javascript로 변환시키는 컴파일러

 

Dart는 JIT(just-in-time), AOT(ahead-of-time) 에 의해 컴파일되는데 

 

AOT란?

코드를 실행하기 전에 사전 컴파일을 통해 네이티브 머신 코드로 변환하는 과정으로 Dart뿐만 아니라 C, C++, Rust, Go 같은 언어에서도 널리 사용되는 방식이다

 

예를 들어, C나 C++ 같은 언어로 코딩한 경우, 실행 파일을 생성하기 위해 컴파일 시 운영체제와 CPU 아키텍처에 맞는 바이너리를 생성해야 하는데 Windows에 배포하려면 Windows용 실행 파일로 컴파일해야 하며, Linux나 macOS에 배포하려면 각각의 플랫폼에 맞는 실행 파일로 컴파일해야 합니다.
C 컴파일러는 이 과정을 통해 코드를 기계어로 변환하여 사람들이 컴퓨터에서 해당 프로그램을 실행할 수 있도록 해준다.

이렇듯, 코드를 실행하기 전에 컴파일을 완료하고, 그 결과로 생성된 바이너리를 배포하는 방식이 AOT.

개발시 AOT를 사용하게 된다면 코드 수정시 확인하고 싶을때마다 처음부터 모든걸 컴파일을 해야 하기 때문에 시간이 매우 많이 걸리고 번거롭다.

 

JIT란?

dart VM을 사용하여 작성한 코드의 결과를 바로 화면에 보여준다.

코드를 실행하면서 필요한 부분만 즉석에서 컴파일하므로 개발 속도를 높이지만, 실행 속도는 AOT보다 느릴 수 있다.

그러나 JIT를 사용하면 핫 리로드 기능을 통해 개발 중 코드 변경 사항을 즉각적으로 확인할 수 있다

그렇기 때문에 JIT는 개발중에만 사용된다.

 

dart 가상머신이 풍부한 디버깅과 함께 JIT컴파일러를 제공하고있기 때문에 개발 결과를 즉각 확인할 수 있다.

개발이 완료되과 app 배포 시 dart VM이 아닌 AOT 컴파일러를 사용하여 다양한 아키텍쳐에서 사용할 수 있게된다.

 

2. null safety를 통한 안전한 프로그램이다

null 참조 오류는 런타임 크래시의 주요 원인 중 하나이므로, Dart는 Null Safety를 도입하여 컴파일 단계에서 이러한 오류를 방지한다.

Null Safety는 선언된 변수에 null 값을 허용할지 명시적으로 결정하게 함으로써 프로그램 안정성을 높인다.

2. flutter는 왜 dart를 택했을까?

1. JIT와 AOT 컴파일이 둘 다 있다

그래서 빠른 피드백을 원하면서 최종 앱의 컴파일이 빠르기 때문에 모바일 개발에 아주 좋은 언어라 할 수 있다.

 

2. dart와 flutter 둘 다 구글에서 만들었다.

그래서 flutter를 위해 dart를 최적화 할 수 있다.


처음 시작할 때 dart나 flutter를 설치하지 않아도 dartpad.dev 사이트에서 바로 연습할 수 있다.

https://dartpad.dev/

 

DartPad

 

dartpad.dev

 

1.any 타입

☑️ any란?

  • TypeScript에서 any 타입은 모든 타입의 슈퍼 타입이에요.
  • 이는 어떤 타입의 값이든 저장할 수 있다는 의미입니다!
  • JavaScript의 object 타입과 같은 최상위 타입이라고 생각하시면 됩니다!

☑️ 사용 사례

let anything: any;
anything = 5; // 최초에는 숫자를 넣었지만
anything = 'Hello'; // 문자열도 들어가고요
anything = { id: 1, name: 'John' }; // JSON도 들어가네요

2.unknown 타입

☑️ any의 대체제 unknown이란?

  • unknown 타입은 any 타입과 비슷한 역할을 하지만 더 안전한 방식으로 동작합니다.
  • unknown 타입의 변수에도 모든 타입의 값을 저장할 수 있어요.
  • 하지만, 그 값을 다른 타입의 변수에 할당하려면 명시적으로 타입을 확인해야 합니다!

☑️ 사용 사례

let unknownValue: unknown = '나는 문자열이지롱!';
console.log(unknownValue); // 나는 문자열이지롱!

let stringValue: string;
stringValue = unknownValue; // 에러 발생! unknownValue가 string임이 보장이 안되기 때문!
stringValue = unknownValue as string;
console.log(stringValue); // 나는 문자열이지롱!
  • stringValue = unknownValue as string; 코드를 **Type Assertion(타입 단언)**이라고 합니다.
  • unkwown 타입의 변수를 다른 곳에서 사용하려면 타입 단언을 통해 타입 보장을 하여 사용할 수 있어요!
let unknownValue: unknown = '나는 문자열이지롱!';
let stringValue: string;

if (typeof unknownValue === 'string') {
  stringValue = unknownValue;
  console.log('unknownValue는 문자열이네요~');
} else {
  console.log('unknownValue는 문자열이 아니었습니다~');
}
  • 타입 단언만이 답은 아닙니다!
  • typeof 키워드를 이용하여 타입 체크를 미리한 후 unknown 타입의 변수를 string 타입의 변수에 할당할 수 있어요!

3. union

☑️ unknown의 한계

  • unknown 타입이 그나마 재할당을 할 때 타입 체크가 되어서 안전함을 보장해요.
  • 하지만, unknown 타입도 결국 재할당이 일어나지 않으면 타입 안전성이 보장이 되지 않아요ㅠㅠ

☑️ union이란?

  • 이럴 때를 위해 union 타입이라는 것이 사용됩니다.
  • union 은 여러 타입 중 하나를 가질 수 있는 변수를 선언할 때 사용됩니다!
  • union은 | 연산자를 사용하여 여러 타입을 결합하여 표현합니다.

☑️ 사용 사례

type StringOrNumber = string | number; // 원한다면 | boolean 이런식으로 타입 추가가 가능해요!

function processValue(value: StringOrNumber) {
  if (typeof value === 'string') {
    // value는 여기서 string 타입으로 간주됩니다.
    console.log('String value:', value);
  } else if (typeof value === 'number') {
    // value는 여기서 number 타입으로 간주되구요!
    console.log('Number value:', value);
  }
}

processValue('Hello');
processValue(42);

'develop > type script' 카테고리의 다른 글

type script readonly  (0) 2023.12.20
typeScript 튜플(tuple)  (0) 2023.12.20

☑️ readonly란?

  • 앞의 두 키워드는 JavaScript에서 많이 사용되는 키워드죠.
  • 하지만, readonly는 TypeScript에서 등장한 키워드에요!
  • readonly는 TypeScript에서 객체의 속성을 불변으로 만드는 데 사용되는 키워드에요!
  • 즉, 클래스의 속성이나 인터페이스의 속성을 변경할 수 없게 만들 수 있습니다.

☑️ 사용 사례

class Person { // 클래스는 다른 강의에서 자세히 설명해드릴게요!
  readonly name: string;
  readonly age: number;

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

const person = new Person('Spartan', 30);

console.log(person.name);  // 출력: 'Spartan'
console.log(person.age);   // 출력: 30

person.name = 'Jane';  // 에러: 'name'은 readonly 속성이므로 다시 할당할 수 없어요!
person.age = 25;       // 에러: 'age'은 readonly 속성이므로 다시 할당할 수 없어요!

<aside> ⁉️ readonly를 const로 치환하면 어떻게 되나요? 이렇게 쓰면 안되나요?

</aside>

  • 클래스의 속성에 const 키워드를 사용할 수 없다고 편집기가 에러를 뿜습니다!
  • const 키워드는 일반 변수를 상수화 할 때 사용하는 것이에요!

'develop > type script' 카테고리의 다른 글

any,unknown, union  (1) 2023.12.20
typeScript 튜플(tuple)  (0) 2023.12.20

☑️ 튜플이란?

  • 튜플은 서로 다른 타입의 원소를 순서에 맞게 가질 수 있는 특수한 형태의 배열입니다.

☑️ 튜플과 배열의 차이

  • 배열은 number[], string[] 처럼 같은 타입의 원소만 가질 수 있었어요.
    • const testScores: number[] = [90, 85, 78, 92, “88”];
      • 위의 코드처럼 마지막 원소를 string 타입으로 넣으면 에러가 발생하죠!
      • 숫자만 넣어줘야 합니다. 즉, 같은 타입의 원소만 취급할 수 있어요.
  • 하지만, 튜플은 어떤 타입의 원소를 허용할 것인지 정의만 해주면 됩니다.
    • 얼마든지 허용된 타입의 데이터들을 저장할 수 있어요!

☑️ 사용 사례

const person: [string, number, boolean] = ['Spartan', 25, false];
const person2: [string, number, boolean] = [25, 'Spartan', false]; // 오류!
  • 여기서는 string, number, boolean이라는 3개의 각각 다른 타입의 데이터를 보관하게 정의를 했어요!

<aside> ⁉️ person이라는 튜플에 데이터를 더 저장하고 싶은데 그래도 상관없나요?

</aside>

  • 원칙적으로는 데이터를 더 저장하는 것은 타입 안정성에 위배가 되는 행위에요!
  • 따라서, 정의된 데이터 타입의 개수와 순서에 맞추어 저장을 하는 것이 필수입니다!
  • 튜플에서도 배열의 메소드인 push를 사용하여 정의된 데이터 타입의 개수보다 더 저장할 순 있어요.
    • 하지만, 이렇게 억지로 데이터를 넣으면 튜플 구조가 내부적으로 변경이 되니 좋은 선택은 아니에요!

'develop > type script' 카테고리의 다른 글

any,unknown, union  (1) 2023.12.20
type script readonly  (0) 2023.12.20

+ Recent posts