やすくて速い正規表現(Easy Regular Expression)

正規表現の構成と意味、ジャバスクリプト(Javascript)でのお扱い

正規表現というのは検索パータンを指定し記号で表示したものです。

このアイデアはアメリカの数学者であるスティーブンコールクリーン(Stephen Cole Kleene)が1950年代に正義した正規言語(Regular Language)と関係がありまして、正規表現の文法は1980年代にパール(Perl)言語から使い始まりました。

主に、検索や置換の作業に使われ、皆が使うほとんどのプログラミング言語の中でサポートされている文法です。

例えば、次の文章の中で特定した条件を検索するとき正規表現の力を借りることができます。

The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it.

  • ‘too’ 文字列を検索する -> /too/
    The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it.
  • 大、小文字を構わなく ‘t’ 文字を検索するとき -> /t/-gi
    The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it.
  • ‘d’ から始まる単語及び文字のすべてを検索するとき -> /[d]\w+/-gi
    The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it.
  • ‘ea’を含む単語を検索するとき -> /[a-z]*ea[a-z]*/-i
    The greatest danger for most of us is not that our aim is too high and we miss it, but that it is too low and we reach it

正規表現の文法テストは次のページが助かります。

regexr.com

青いバーExpressionの下のインプットには表現を入れ書き、その下のボックスには検索対象になるテキストを入れればオッケーです。

まず、表現の意味について少し勉強してからJavascriptで楽に使う方法を確認してみます。


1. 正規表現の記号

  • / . / → すべての文字
  • / + / → 一つ以上の文字
  • / ? / → 0または一つの文字
  • / ^ / → 該当の文字を除く
  • / / → 範囲指定
  • / * / → 0または一つ以上の文字
  • / [ ] / → グループセット
  • / { } / → 繰り返しの回数指定
  • / \ / → エスケープ
  • / \d / → すべての数字
  • / \D / → 数字ではない文字
  • / \w / → アルファベット、数字、アンダーバー
  • / \W / → アルファベット、数字、アンダーバーではない文字
  • / \s / → 空白文字
  • / \S / → 空白ではない文字
  • / \n / → 改行

基本的に正規表現を構成する記号は上記であり、この記号さえ覚えれば正規表現の基本的な仕組みは十分理解できると思います。

それではサンプルを参考しながら正規表現を分析していきましょう。


2. 記号の意味

正規表現で一番基礎になる記号であるので覚えておくと役に立ち部分です。

dは数字、 wは英文字、 sは空白、 nは改行の意味であり、各文字の大文字は NOT(反対)を示します。

  • 数字が一回以上繰り返す文字検索 ? / [\d]+ /
  • 数字ではない文字を検索(空白含む) ? / [\D] /
  • 括弧(かっこ)が含まれている文字、数字検索 ? / \([\w]+\) /
  • 英文字、数字、アンダーバーではない文字検索 ? / [\W]+ /
  • 空白検索 ? / \s /

上で紹介したregexr.comで検索対象になるテキストをいれてパータンを直接に作成してみるとすぐ正規表現になれると思います。


大体エスケープというのは何ですかね。

キーボードの一番左一番上のキー(ESCと書かれているもの)がエスケープの略字です。エスケープの意味は逃れるのです。

こちらでは約束から逃れることだと認識すればいいと思いです。

例えば、正規表現で点(. dot)はすべての文字の意味にしようと約束した特別な文字ですね。

でもたまには’それ約束以外’に点をピリオド意味の点で使いたいときがありますね。

この時エスケープを使います。

エスケープを使わない限り、文字は約束した機能として動きます。

下の例で確認しましょう。

  • すべての文字を意味。 a, b, c, d, ?, !, @, , などすべての文字の中一つ ? / . /
  • エスケープを前につけるとただピリオド記号だけの意味 ? / \. /
  • 一つ以上の文字の意味 ? / + /
  • エスケープを前につけるとただプラス記号だけの意味 ? / \+ /

エスケープはよく使われる必須な機能であるので、そのままの文字にはならないのでエスケープが必要な特別な文字(. ? + *など)を覚えておく必要があります。

その文字の一部を下で紹介します。


上で紹介した特別な記号は特別な意味を持ちます。代表的な使い方は下の通りです。

  • 小文字a~z或は大文字A~Z中一致する英文字検索 ? / [a-zA-Z] /
  • color或はcolourを検索(‘u’があってもなくてもいい) ? / colou?r /
  • ‘a’を含む単語検索 ? / [\S]*a[a-zA-Z]* /
  • a-z或は空白(space)ではない文字検索 ? / [^a-z ] /
  • 英文字から始め必ず数字または特殊記号を含む文字列を検索 ? / [a-zA-Z]+[\d!@#\$%\^*]+[\w]* /

中括弧は繰り返しの回数を指定し、これを使うと詳しい検索パータンの設定が可能です。

中括弧の中、一つの数字は全体の繰り返し回数の意味であり、二つの数字は頭と末の範囲を指定する意味です。

例え、{3}は3回繰り返しの意味であり、{1, 3}は範囲区間1から3の意味です。

{1, }のような表現も可能であり、これは+記号と同様な意味, つまり一つ以上の意味であります。

  • Aが3回繰り返す文字を検索 ? / [A]{3} /
  • 3桁以上の数字を検索(3번以上繰り返し) ? / [\d]{3,} /
  • Aが二回から三回まで繰り返す文字を検索(繰り返す範囲指定) ? / [A]{2,3} /

繰り返し回数だけを指定すれば、意図しない結果が出ることがあるので、部分式(subexpression)と全後方一致検索を一緒に使うともっと効果的なパータンが可能です。


角かっこの中に記号を書き、検索パータンを指定します。直接に記号を書き込んだり、範囲指定記号の’-‘を使ってパータンを指定します。

  • 指定する文字(a 或は A 或は b 或は B 或は c 文字)一つを検索 ? [aAbBc]
  • aから eまで(a,b,c,d,e)の範囲内一つの文字を検索 ? [a-e]
  • 除外文字’^’があるので a-z 範囲に入らない文字(記号)を一つ検索 ? [^a-z]
  • 明記した記号の一つを検索 ? [?!@#$%^&*()_]
  • c或はCから始め, a-zの中一つで終わる単語検索 ? [cC][a-z]

[ ]を使うと一つだけの文字を検索するので一つ以上の文字を検索したいときには+記号(一つ以上の文字、0は不可)または*(0または一つ以上の文字、0も可能)記号を付ける必要があります。

  • 一つ以上のa-z文字を検索(必ず一つ以上の条件) ? [a-z]+
  • 0個以上のA-Z文字を検索(なくてもいい) ? [A-Z]*

特定構成で成り立つ文字列の検索に効果的であり、例えばメールアドレスの文字列があります。

メールアドレス形式のabcd@xyz.comを検索するためには次のようなパータンを使うことができます。

/[a-zA-Z0-9]+@[a-zA-Z0-9]+\.[a-zA-Z]+/

では、パータンを分析してみます。

先、メールのIDになる部分は英文字と数字が入るので、[a-zA-Z0-9]で始め一つ以上を意味する+記号を付けます。

その次、@が続きますので@を入れ, ホストのアドレスも一つ以上の英文字と数字を指定します。

.com形のアドレスなのでピリオドをそのまま使うためエスケープを使いまた一つ以上の英文字を入れてパータンを生成します。

もしIDの中に点が入るかホストアドレスが.co.jpなどの形になるときにはそれに対する応用が必要です。



3. まとめ

正規表現の第一印象はまるで外界言語みたいな姿で広く使われる既存の言語とは違う様子をしてますね。

軽く近づけられなくいやな気持がするときもありますが、少しだけでも調べてみたら意外と簡単な規則でパワフル機能を持っていいやつだなと思われる時が来るかもですね。

上で紹介した部分は代表的な機能を紹介するため簡単なパータンたちなので、上のパータンは不完全なパータンであります。もの正しいパータンを作るためにはもっと深く勉強する必要がありますね。

ご質問がありましたら、自由にコメントください!

あざーす!

AWS EC2 – From Launch New Instance To Install Everything We Need

Simple Explanation Of Setting up AWS EC2(Ubuntu18.04)

1. Launch New Instance In AWS

On a EC2 Management Console page, launch instances and choose Ubuntu Server 18.04 LTS with adequate instance type.

I chose t2 micro Type and launched.

On the next page, click Edit security groups and open port 22, 80, 443 for the next step.

Before launch the instance, you should select an existing key pair or create a new one.

If you don’t have any, create a new one and download key pair.

You should keep that key pair safe and don’t let be exposed to anyone.

We need an elastic IP address(Non-change address) for our accessibility.

Elastic IP lasts forever even if you stop the instance unless you release the IP address.

EC2 -> Network & Security -> Elastic IPs -> Allocate Elastic IP address.

Associate Elastic IP address and Choose an instance to stick them together.

Half way there.

Now you have your own instance and elastic IP address.

Keep going.

2. Connect To The Server Using SSH Client

You can use any SSH Client whatever you want.

This time I chose XShell7 that is free for Home/School.

Put the IP address in Host textbox.

Go to Authentication, write User Name ‘ubuntu’ and check Method Public Key.

Click Connect.

Browse and select the key pair that we downloaded.

If you get this message, now you are in.

3. Install Nodejs On Ubuntu Server

$ curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -

$ sudo apt-get install -y nodejs

Execute line by line and when it’s done, we can check by ‘node -v’ command.

If node version(v14.18.2 or something) is printed, installation is done.

4. Install MongoDB On Ubuntu Server

$ wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -

If you see ‘OK‘ return with above command, you are ready for the next step.

$ echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list

If you see ‘echo “deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse” | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list‘, move forward.

$ sudo apt-get update
$ sudo apt-get install -y mongodb-org

If you feel like something goes on a busy process, just wait.

When it’s done, check an installation with this command.

‘mongo -version’

Start mongodb service with this command.

$ sudo service mongod start

When successfully started, no message output.

$ mongo

> use admin

> db.createUser({ user:'id', pwd:'pwd', roles:[{"role":"userAdminAnyDatabase","db":"admin"},{"role":"readWriteAnyDatabase","db":"admin"}]})

exit

Have to change some codes for accessibility and security.

$ sudo vi /etc/mongod.conf

binIp : 127.0.0.1 -> bindIp: ::, 0.0.0.0

#security -> refer to above capture. no space before ‘enabled’ makes error.

save it!(‘wq’ command)

If you want to give a access try, use Compass with 27017 port opened.

5. Deploy(git clone)

Use Git, clone your project to your instance and install dependencies.

$ git clone https://github.com/id/repo

$ cd repo
$ npm install

6. Run Server With PM2

Install pm2 and run your own server.

pm2 makes your server keep running if you close the shell.

$ sudo npm install pm2 -g

$ sudo pm2 start index.js //in my case with arguement -> sudo pm2 start src/index.js --node-args="-r esm"

Now, your server won’t stop unless you stop the PM2.

You can check the PM2 status with below command.

$ sudo pm2 list

7. Install Nginx On Ubuntu Server

Nginx has additional functions that Nodejs do not have.

Simply in two ways, security and load balancing.

$ sudo apt-get install nginx

We opened port 80 for Nginx access.

When Nginx works, clients come in through Nginx door and Nginx leads them to internal port.

$ sudo service nginx start

When Nginx started, access it with your ip address.

Like http://3.34.65.190

Nginx welcomes you if you are on right process.

Now, Change some codes as below with vi editor to complete Nginx work.

$ cd /etc/nginx/sites-enabled

sudo vi default

Comment out try_files $uri $uri/ =404; and add

    proxy_pass http://yourIP:port/;
    proxy_set_header Host $http_host;
    proxy_http_version 1.1;
    proxy_set_header X-Nginx-Proxy true;
    proxy_redirect off;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_pass takes clients to internal port that you set on Nodejs.

In my case, http://3.34.65.190:4000/;

Save it.

Next step is set a size limitation.

Nginx’s default file size setting is 1MB.

But if your page handles bigger than 1 MB files upload or download, this setting is necessary.

$ sudo vi /etc/nginx/nginx.conf
client_max_body_size 10M(limit size that you want);

Now, restart Nginx.

sudo service nginx restart

Now you can access you page that you made.

8. SSL certificate with Let’s Encrypt(http ->https)

Using Route53 service, get a own domain and manage DNS.

Redirect to your IP address and when you have your own domain, you can get a SSL certification with Let’s Encrypt for free.

$ sudo add-apt-repository ppa:certbot/certbot

$ sudo apt install python-certbot-nginx

$ sudo certbot --nginx -d yourdomain.com

Follow the direction, and then your web can get a SSL certification and https protocol is available.

The direction is simple.

1. enter your email address

2. Agree

3. Yes(or No)

4. choose No.2 (redirect http to https option)

And that’s it.

Important thing for the last step is opening the port 443.

Port 443 is a port for https.

Restart Nginx and access with your domain address.

Automatically https will welcome you.

Every 90 days, certification renewal is required and below is the command.

$ sudo certbot renew --dry-run

AWS : aws.amazon.com

맛깔나는 게국지 쉽고 빠르게 만들기(꽃게탕)

게국지와 꽃게탕 그 중간쯤..

요리 재료

쌀뜨물 1.5L

멸치 다시 육수 1팩(또는 다시마 + 멸치 약 8마리)

참실한 게 2마리

양파 반개

빨간 소스(고춧가루 3스푼, 멸치액젓 2스푼, 소주 1스푼, 설탕 1스푼, 진간장 2스푼, 간마늘 2스푼)

된장 2스푼

콩나물 한 줌

청양고추 1개

파(꽤 많이)

건새우(옵션)

신김치(옵션)

요리 시작

쌀뜨물 + 멸치다시 + 건새우 + 게2마리 + 양파 반개 + 소스 + 된장을 때려 넣고 뽀글뽀글.

끓어오르면 콩나물 + 청양고추 + 파 + 신김치를 넣고 NO뚜껑에 살짝 약한 불로 20분간 더 끓입니다.

네 끝이에요.

배를 뒤집고 누워있는 게 친구.

Nodejs에서 배치(Batch) 기능 사용하기(node-schedule)

예정된 시간에 작업을 수행하는 node-schedule

별도의 SQL문을 사용해 배치(Batch) 기능을 사용하던 것과 비교하면 정말 편하게 프로그래밍이 가능하도록 도와주는 라이브러리입니다.

배치 기능을 사용할 수 있는 대표 라이브러리는 크게 3가지(Agenda, node-cron, node-schedule)이며, 인기는 다음과 같습니다.

  1. Agenda (2021/12/22 기준 주간 다운로드 수 56,319)
  2. node-cron(2021/12/22 기준 주간 다운로드 수 219,168)
  3. node-schedule(2021/12/22 기준 주간 다운로드 수 507,675)

필요한 기능이 동일하다면 사용자가 많은 쪽이 관련 정보도 얻기 쉬우므로 node-schedule을 사용해보겠습니다.

npm install node-schedule

설치 후 해당 라이브러리를 import합니다.

import schedule from 'node-schedule';

그리고 서버를 가동하면 바로 실행될 수 있도록 index.js에 실행 함수를 넣어주면 됩니다.

실행될 조건(시간 또는 반복 주기)을 넣어주면 해당 조건에 맞춰 함수를 실행합니다.

const regularExec = schedule.scheduleJob('0 0 12 * * *', ()=>{ // 매일 낮 12시 정각마다 실행

    sendCheckDataEmail();

})

위 함수는 매일 낮 12시마다 실행됩니다.

scheduleJob의 첫 번째 파라미터의 값은 다음과 같습니다.

*는 all과 값은 의미이며, 각 파라미터의 사이에는 빈칸을 넣어줍니다.

초를 넣는 부분인 second 에 *를 넣으면 모든 초마다 실행하라는 의미가 됩니다.

따라서 minute에 5, second에 *을 넣으면 5분00초부터 5분59초까지 함수가 총 60번 실행됩니다.

주기를 설정하는 방법도 있는데요.

second에 */5로 표기하면 초 단위를 5초 단위로 쪼갭니다.

따라서 5초에 한 번씩 실행하라는 의미가 됩니다.

취소는 cancel 메소드를 사용하면 됩니다.

regularExec.cancel();

유의할 점은 서버가 실행 중일 때만 해당 스케쥴러가 작동하며, 멀티프로세스를 가동하는 경우 중복으로 실행되지 않도록 별도의 설정을 해주어야 합니다.

그럼 서버가 열심히 일하도록 스케쥴러 기능을 요긴하게 사용해 주세요!

Nginx와 AWS S3, 왜 큰 용량은 업로드가 안돼?(413 Request Entity Too Large, React, Koa)

Nginx 업로드 용량 제한 설정이 필요한 이유

React, Koa를 사용하고 Nginx를 거쳐 파일 업로드 진행하는 프로세스에서 프론트와 백엔드에서 각각 파일 크기를 체크한 뒤 AWS S3에 저장을 진행하도록 하였으나 다음과 같은 에러가 발생하는 경우가 있습니다.

이미 파일 크기 체크를 진행하고 업로드한 파일이 용량 문제로 에러가 발생한다니 이건 뭐지 싶지만 답은 Nginx에 있습니다.

Nginx는 큰 용량의 파일을 대량으로 업로드하는 서버 공격을 막고자 기본 전송 용량 설정이 1MB로 되어 있습니다. 따라서 1MB 이하의 파일을 한번 업로드해보면 바로 해결의 실마리를 찾을 수 있습니다.

위와 같이 1MB 이하의 파일은 아주 잘 올라갑니다.

설정을 위해 커맨드에서 아래와 입력합니다.

# sudo vi /etc/nginx/nginx.conf

nginx.conf 내부 http 부분에서 client_max_body_size로 설정을 진행합니다.

기본값은 1MB이며, client_max_body_size는 기본적으로 명시되어 있지 않으므로 별도로 입력이 필요합니다.

아래와 같이 http{ } 내부에 client_max_body_size와 원하는 용량을 함께 기입해주고 Nginx를 재시작합니다.

50MB로 설정해두고, Nginx를 리셋해 보겠습니다.

# sudo service nginx reload

다시 업로드해보면 이제는 1MB 이상의 파일도 문제 없이 업로드 되는 것을 확인할 수 있습니다.


참고자료 : https://www.cyberciti.biz/faq/linux-unix-bsd-nginx-413-request-entity-too-large/

엑셀과 인코딩(UTF-8)의 싸움, 이젠 끝내기로 해(feat.몽고MongoDB와 날짜 처리)

엑셀 인코딩 문제를 해결하고, mongoDB에 깔끔하게 저장하는 방법

주로 csv 형식의 파일을 열거나 하나의 프로그램에서 다른 형식의 문서를 불러오면 아래와 같은 문자를 만나는 경우가 있습니다.

�����������Ǹ�

.<-9xH#,;}<:@O,A& 8q,;

이는 문자 인코딩에서 발생하는 문제로, 영어로 썼는데 프랑스어로 해석하는 것과 비슷하다고 보시면 될 것 같습니다.

인코딩 문제는 주로 비알파펫(非 ALPHABET) 언어를 사용하는 곳에서 자주 발생합니다.

컴퓨터에서 처음 문자가 사용될 때는 한 문자 당 1바이트를 사용하는 알파벳만 지원되었으므로 이 때는 문자 인코딩이고 뭐고 할 게 없었습니다.

그러나 차츰 컴퓨터의 사용 영역이 넓어지고 컴퓨터에서 처리할 수 있는 데이터도 늘어나자 다른 언어를 지원하기 위한 방법이 연구되었고, 그 결과 다양한 문자 인코딩이 탄생하였습니다.

한글과 관련한 인코딩만 찾아봐도 아래와 같이 다양합니다.


ASCII(American Standard Code for Information Interchange)

-7bit로 구성되며, 128개의 영문자를 표현

ANSI(American National Standard Institute)

-8bit로 구성되며, 256개의 문자를 표현

EUC-KR(Extended Unix Code – Korea)

-16bit로 구성되며, 글자 하나하나에 부여된 코드를 사용. 중국어, 일본어, 한국어 등의 표현에 사용

CP-949(Code Page 949)

– Windows의 코드 조합으로 EUC-KR의 확장

UTF-8(Universal Coded Character Transformation Format 8 bit)

– 가변 길이 문자 인코딩으로 1~4바이트까지 사용. 우리가 원하는 그것.


위와 같이 다양한 방식을 사용해 문자를 표현하고 있습니다.

하지만 우리를 화나게 하는 것은 엑셀에서 csv로 내보낸 파일을 다른 프로그램(또는 DB)에서 불러오려고 하면 ‘???????’ 라고 표현하는 그것일 것입니다.

원인을 살펴보면, 해당 문제를 겪는 대부분은 Windows + 엑셀의 조합일텐데요.

Windows는 기본적으로 CP-949로 인코딩을 하지만 읽는 프로그램은 UTF-8을 사용하다 보니 주로 발생하는 문제입니다.

따라서 인코딩 시 UTF-8로 내보내기만 하면 문제는 해결되지만 Windows는 쉽게 UTF-8로 바꿔주려고 하지 않습니다…

그래서 엑셀로 내보내는 csv 파일을 UTF-8로 변환하는 방법에 대해 알아보겠습니다.

위와 같은 데이터를 가진 엑셀 친구를 UTF-8 형식으로 만들어 보겠습니다.

먼저 저 친구를 그냥 csv로 내보내기를 하면 Windows에서 지정한 인코딩 형식으로 내보내기가 됩니다.

확인해볼까요?

엑셀 2010을 사용해 테스트를 진행해보겠습니다.

다른 설정 없이 위와 같이 CSV 형식으로 다른 이름으로 저장을 하고 mongoDB에서 가져오기를 하면 다음과 같이

‘알아듣게 얘기하라’는 식의 반응을 보입니다…

그럼 이제 엑셀에서 인코딩 형식 지정하여 내보내기를 해보겠습니다.

저장 시 위와 같이 [도구-웹 옵션]으로 들어가면

이렇게 친절하게 [인코딩] 탭에서 인코딩 형식의 지정이 가능합니다…..만

파일명을 test(set).csv로 저장해보았습니다.

하지만 mongoDB에서 위 파일을 불러오면

mongoDB가 왜! 뭐! 라고 하는 것 같습니다.

엑셀에서 인코딩 형식을 지정해도 제대로 반영이 되지 않는 것 같습니다.

물론 최신 엑셀에는 ‘csv 내보내기(UTF-8)’과 같은 방식의 확장자 유형의 선택이 생겼으나 현재는 엑셀 최신 버전이 없어 서 테스트가 불가하므로… 다음.

여기서는 다른 방식으로 인코딩 형식을 변경해 보도록 하겠습니다.

엑셀로 저장한 csv를 메모장으로 불러옵니다(엑셀 파일이 아닌 csv 파일입니다).

메모장에서 ‘다른이름으로 저장’을 선택하여 아래와 같이 인코딩을 UTF-8로 변경해줍니다.

csv 파일 형식은 유지해야 하므로 파일 형식은 모든 파일(*.*)로 변경해주고 파일 이름의 확장자에는 .csv를 유지합니다.

그리고 다시 한번 mongoDB에서 조우를 해보겠습니다.

더이상 반항하지 않습니다.

하여, IMPORT를 눌러보면!

문맹은 벗어났으나….

이제는 날짜를 못 알아먹네요.

날짜도 입맛에 맞게 맞춰주겠습니다.

먼저 날짜를 모두 선택하고 ‘.’으로 구분된 기호를 ‘/’로 변경해줍니다.

CTRL + H를 사용합니다.

변경 후 해당 칼럼(또는 해당 셀)을 날짜 형식으로 변경해줍니다.

DB에 저장될 타입을 Date로 변경해줍니다.

그리고 마지막으로 기회를 한번만 더 주겠습니다.

그리고 IMPORT!

더 이상 반항을 하지 않는 착한 데이터를 표현합니다.

위 날짜 데이터는 toLocaleDateString()과 같은 자바스크립트 함수로 깔끔하게 정리해주면 이쁘게 출력이 가능합니다.

그럼 더 이상 엑셀과 인코딩으로 스트레스 받지 않기를 바랍니다.

peace!

자바스크립트, 문자열 함수 마음대로 다루기(Javascript works with string)

Javascript String Methods : slice(), substring(), includes(), startsWith(), trim(), replace()…….

프론트엔드(React, Vue, Angular)와 백엔드(Node.js)가 모두 자바스크립트를 사용하는 시대에 들어서니 자바스크립트의 기초가 몇 배는 더 중요해진 것 같습니다.

자바스크립트의 문법 중 문자열(String) 관련 함수는 참 쓸 일이 많으면서도 가볍게 여겨져 쉽게 외워지지 않는 슬픈 함수 중 하나인 것 같습니다.?

문자열 관련 함수는 한 번 외워두면 반복 학습할 일이 많으므로 첫 단추만 잘 꿰면 될 것 같습니다.

그럼 문자열 관련하여 사용 빈도가 높은 함수인 slice(), substring(), includes(), startsWith(), trim(), replace(), indexOf(), test() 함수에 대해 알아보겠습니다.


slice 함수는 위치(인덱스)를 매개변수로 전달하여 원하는 문자열을 추출합니다.

시작 위치(필수)와 종료 위치(옵션)를 전달하며, 시작 위치만 전달하는 경우 시작 위치부터 문자열 끝까지 추출합니다.

0은 순방향으로 첫 번째(앞에서 1번 째), 음수인 -1은 역방향으로 첫 번째(뒤에서 1번 째)를 나타냅니다.

const myWord = 'primavera';

myWord.slice(0,5);   // 'prima'
myWord.slice(-4);    // 'vera'
myWord.slice(3);     // 'mavera'

myWord.slice(3,1);    // '' -> slice함수는 시작인덱스가 종료인덱스보다 크면 빈 값을 반환

substring 함수도 slice와 마찬가지로 위치(인덱스)를 매개변수로 전달하여 원하는 문자열을 추출합니다.

기본적인 작동 방식은 같으나 slice와 달리 시작인덱스가 종료인덱스보다 큰 경우에는 자동으로 두 값의 위치를 변경하여 함수를 실행합니다.

또한 substring은 매개변수에 음수를 넣으면 이 값을 0으로 인식합니다.

따라서 (3, -1)을 전달하게 되면 (3, 0)으로 인식합니다. (3, 0)은 시작 인덱스가 더 크므로 위치를 변환하여 (0, 3)의 값을 계산한 결과를 반환합니다.

함수명이 비슷한 substr의 경우 ‘위치’와 ‘추출할 문자의 수’를 파라미터로 전달하는 함수입니다.

const myWord = 'invierno';

myWord.substring(3);     // 'ierno'
myWord.substring(1,3);   // 'nv'

myWord.substring(3,1);   // 'nv' -> 시작이 종료인덱스보다 크면 자동으로 위치 변경 후 함수를 실행

myWord.substring(3,-1);  // 'inv' -> 음수는 0, 시작인덱스와 종료인덱스는 위치 변경 후 계산

myWord.substring(-4);    // 'invierno' -> 음수는 0, 시작인덱스만 전달하여 0부터 끝까지 계산

myWord.substr(1,3);      // 'nvi' -> 시작인덱스 1부터 문자 3개를 추출

includes 함수는 지정한 문자열의 포함 여부를 확인합니다.

매개변수로 문자열(필수)과 위치인덱스(옵션)를 전달하며, 반환값은 true 또는 false 입니다.

문자열 내 지정 문자열 확인은 물론 배열 내 빈 값을 확인하는 용도로도 사용할 수 있습니다.

const myWord = 'alegria';

myWord.includes('le');       // true
myWord.includes('i');        // true
myWord.includes('rio');      // false

const myArray = ['dream','','king'];
myArray.includes('');       // true   -> myArray[1]이 빈 값이므로 true. 배열 내 빈 값을 찾는 용도
myArray.includes('dream');  // true   -> myArray[0]의 값과 일치
myArray.includes('drea');   // false  -> 배열 내 값과 정확하게 일치하는 경우에만 true를 반환

startsWith 함수도 문자열의 포함 여부를 확인하는 함수라고 볼 수 있습니다.

startsWith와 함께 문자열만 전달하면 0 인덱스부터 시작하여 해당 문자열의 존재 여부를 확인하여 BOOLEAN 값을 반환합니다.

마찬가지로 endsWith는 끝나는 문자열을 비교합니다.

const mySentence = 'cafe con leche';

mySentence.startsWith('cafe');     // true
mySentence.startsWith('fe');       // false
mySentence.startsWith('fe',2);     // true

mySentence.endsWith('eche');      // true

trim 함수는 문자열 양 끝의 공백을 제거하는 함수입니다.

문자열 변환 과정이나 실수로 보이지 않는 공백을 삽입하게 되면 문자열 비교 시 겉으로는 동일하지만 결과는

false를 반환하므로 이 trim 함수를 사용하면 문제를 해결할 수 있습니다.

문자열 양 끝의 공백, 탭, 줄바꿈 문자(/n)를 제거하며, 문자열 양 끝이 아닌 부분에는 효과가 없습니다.

const mySentence = '  la casa de papel   ';

mySentence.trim();        // 'la casa de papel'

const mySentence = ' el amor \n';

mySentence.trim();       // 'el amor'

replace 함수는 문자열에서 변경할 기존문자를 찾아 변경문자로 변경합니다.

문자열에서 매개변수로 전달한 기존문자가 여러 개 존재하는 경우 첫 번째로 탐색한 문자열만 변경합니다.

예를 들어, ‘my_name_is_Ron’에서 ‘_’문자를 모두 공백으로 변경하기 위해 replace(‘_’,’ ‘) 함수를 사용해도 결과는 ‘my name_is_Ron’이 반환됩니다.

따라서 문자열에서 해당하는 문자를 모두 변경하고 싶은 경우에는 정규표현식을 사용하면 됩니다.

정규표현식 관련 포스트

const mySentence = 'my name is:Ron';

mySentence.replace(':',' ');        //'my name is Ron'

const mySentence = 'my_name_is_Ron';

mySentence.replace('_',' ');      // 'my name_is_Ron'

//정규표현식 사용해서 모든 문자 변경하기
mySentence.replace(/_/g, ' ');    // 'my name is Ron'

indexOf 함수는 전달하는 문자의 위치를 반환합니다.

이 기능은 원하는 문자열의 앞 또는 뒤에서 문자열을 자를 때 유용하게 사용할 수 있습니다.

예를 들어, ‘Z001-03’이라는 문자열에서 뒤의 ’03’만 추출하고 싶은 경우 indexOf로 ‘-‘ 문자열의 위치를 찾고 해당 위치의 +1 위치부터 끝까지 문자열을 잘라내면 원하는 값을 가져올 수 있습니다.

만약 같은 문자가 여러 개 존재하는 경우 첫 번째 문자의 위치를 반환하며, 두 번째 매개변수에 시작 위치를 전달하면 시작 위치부터 검색을 시작합니다(시작 위치를 전달하더라도 반환 값은 전체 문자열에서 몇 번째인지를 전달합니다).

뒤에서부터 검색을 시작하는 함수는 lastIndexOf이며, 뒤에서부터 첫 번째로 나오는 문자의 위치를 반환합니다(반환 값은 해당 문자가 앞에서부터 몇 번째인지를 반환합니다).

전달하는 문자가 존재하지 않으면 -1을 반환합니다.

const mySentence = 'Z001-03';

mySentence.indexOf('-');     // 4

mySentence.substring(mySentence.indexOf('-')+1);    // '03'

mySentence.indexOf('D');    // -1

const mySentence = 'Z001-03-02';

mySentence.indexOf('-');    // 4
mySentence.indexOf('-', 5);   // 7

mySentence.lastIndexOf('-')   // 7

test 함수는 정규표현식과 함께 사용하여 매개변수로 전달하는 문자열의 유효성을 확인합니다.

비밀번호에 알파벳, 특수문자 등 포함여부 확인이나 생년월일 형식에 알파벳 등 불필요한 문자의 포함 여부를 효과적으로 확인할 수 있습니다.

const mySentence = /a/;
const myWord = 'baby';

mySentence.test(myWord);   // true

/\d/.test('cookie');       // false \d는 숫자(0~9)를 나타내는 정규표현식
/\d/.test('cookie1');      // true

const typedError = /[ㄱ-ㅎㅏ-ㅣ]/gi;
const inputData = '김ㅊ치와 나물';

typedError.test(inputData);    // true 

이 외에도 다양한 함수들이 많고 또 여러 요구에 맞춰 새롭고 편리한 함수가 계속 나오기 때문에 끊임없는 관심과 업데이트 관련하여 모니터링이 필요할 것 같습니다.

광릉수목원(국립수목원), 마음의 여유를 느끼며 스탬프 투어하기!

국립수목원에서 보내는 여유로운 하루

지인의 추천으로 포천시에 위치한 국립수목원(광릉수목원)에 다녀왔습니다.

서울에서 한 시간 정도 거리에 위치하고 가는 길에는 차도 막히지 않아 상쾌하게 다녀왔습니다.

하루 입장 인원이 제한되어 있고 예약을 통해서만 입장이 가능하므로 붐비지도 않고 여유롭게 하루를 보낼 수 있는 곳이어서 너무 좋았습니다.

방문은 2021년 11월 13일이었으며, 근래 비가 오고 날씨가 쌀쌀해진 관계로 바스락 거리는 낙엽들을 많이 밟으며 걸을 수 있었고 반대로 말하면 잎이 많이 떨어져 휑한 나무 친구들도 꽤 많았습니다.

떨어진 낙엽을 보고 계절의 변화를 직접 느낄 수 있어 너무 좋았고, 풀과 나무 내음은 항상 사람을 기분 좋게 하는 것 같습니다.

– 광릉수목원(경기도 포천시 소흘읍 광릉수목원로 415)

입구에서 여러 자료들을 만날 수 있는데요.

스탬프 투어라는 이벤트가 있습니다.

수목원 내 스탬프를 찍을 수 있는 포인트가 지정되어 있고, 스탬프를 모두 찍으면 소정의 선물을 받을 수 있는데요.

스탬프는 3개/5개/13개/14개에 따른 선물이 있습니다.

선물이 무엇일지 기대감을 품고 하나하나 찍다 보니 13개 스탬프에 성공했는데요.

선물은 아래쪽에서 공개하겠습니다.

1인당 한번의 이벤트만 참여가 가능하므로 저희는 두 장의 스탬프 지도를 들고 시작했습니다.

이렇게 스탬프 별 난이도가 적혀 있구요.

마지막에 나올 때 이 난이도 표를 보니 ‘아 그러고 보니 저긴 별 5개 급의 자격이 있군’하는 생각이 들긴 했습니다..ㅎㅎㅎ

이렇게 생긴 것이 스탬프 포인트구요.

돌아다니면서 스탬프를 찍다 보면 수목원 방문 목적이 스탬프로 착각하게 되는 순간이 있습니다..

스탬프 바닥을 보시고 그에 맞는 곳에 꾹! 하고 찍어주시면 됩니다.

사진을 찍어야 하는데 스탬프만 찍고 온 것 같습니다..

유치원에서 세상을 알아갈 만한 나이의 어린 친구들과 섞여서 순서대로 스탬프를 찍는 제 모습도 생각이 납니다..

위 귀곡산장(화장실)은 별 5개짜리 중 한 곳으로 가는 길에 있습니다.

지도 왼쪽 중간쯤에 위치한 카페인데요.

가격이 조금 비싸긴 하지만 자연 속에서 맛있게 먹을 수 있다면야..

내 카드가 아니라서 막 사라고 부추기긴 했습니다..

‘누워서 하늘을 보세요’라는 안내문이 있는 벤치에서 바라본 하늘입니다.

‘광릉숲’ 포인트 하나를 제외한 나머지 포인트를 모두 완성했습니다.

구경하고 쉬고 먹고 걷고 하다 보니 약 3~4 시간 정도 소요된 것 같습니다.

‘광릉숲’ 포인트는 수목원 외부에 있고, 거리가 왕복 약 3.1km로 기재되어 있었는데요.

배가 고파 오늘의 미션은 13개로 마무리하고 선물을 수령하러 갔습니다.

선물은 바로!

스탬프 13개 완성 선물은 펜 + 엽서 + 조각맞추기(?)입니다.

스탬프 14개 선물은 조각맞추기(?)를 하나 더 준다는 차이가 있었던 것 같은데요.

무리하지 말고 13개로도 충분히 만족할 만한 선물을 받을 수 있는 것 같습니다.

스탬프 3개 – 펜

스탬프 5개 – 엽서

스탬프 13개 – 펜 + 엽서 + 조각맞추기(?)

스탬프 14개 – 펜 + 엽서 + 조각맞추기(?) 2개

선물 교환 장소에 스탬프에 따른 선물이 적혀있었는데 힘이 들어 사진도 못 찍었네요..

개인적인 생각으로 5월/6월/10월/11월초가 방문하기 가장 좋은 시기라고 생각됩니다.

예약은 보통 방문 예정 날짜로부터 한 달 정도 여유를 두고 해야 할 만큼 인기가 많은 곳이다 보니 계획적으로 준비하여 방문하시면 정말 좋은 추억을 남길 수 있는 곳이라고 생각됩니다.

매표소 앞에 있는 주차 요금 정산소에서 정산 시 할인 차량(장애인/유공자/저공해차량 등)의 할인도 받을 수 있으니 참고해 주세요.

국립수목원 예약 : https://kna.forest.go.kr/kfsweb/kfi/kfs/cms/cmsView.do?mn=UKNA_01_03_01&cmsId=FC_003267

깃허브(Github) PUSH와 Personal Access Token 문제 해결하기

Support for password authentication was removed on August 13, 2021. 에러

깃허브의 정책 변경으로 인해 8월 13일부터는 개인 액세스 토큰을 사용해야 푸시(PUSH)가 가능하도록 변경이 되어

설정하는 방법을 간략하게 알아보겠습니다.


1. 토큰 발급

vscode에서 푸시를 진행하면 8월 13일 이후로는 위와 같은 에러 메시지와 함께 토큰을 사용하라는 에러가 발생합니다.

토큰 발급은 다음 페이지에서 진행합니다.

https://github.com/settings/tokens

접속하여 Generate new token 클릭

위 페이지에서 Note, Expiration, Select scopes 항목을 선택하면 됩니다.

Note는 토큰 설명, Expiration은 만료 기간, Select scopes는 범위를 지정합니다.

기본적인 범위만 지정하고 싶은 경우 Select scopes는 repo만 체크하면 됩니다.

위 세 항목 작성 및 체크 후 Generate token을 클릭합니다.

토큰이 생성되면 위와 같이 확인할 수 있으며, 생성된 토큰은 홈페이지에서 재확인할 수 없으므로 복사해두고 사용하시면 됩니다.


2. 자격 증명 설정하기

발급 받은 토큰을 윈도우의 자격 증명에 설정하면 작업이 완료됩니다.

윈도우에서 자격 증명 관리자를 실행합니다.

Windows 자격 증명을 선택하면 아래와 같이 github 자격 증명을 확인할 수 있습니다.

위와 같은 형식으로 된 부분을 선택하여 편집을 클릭합니다.

위에서 발급 받은 토큰을 복사하여 암호 부분에 붙여넣기 및 저장하면 작업이 완료됩니다.


CSS Combinators, make your CSS works easier (+,~, ,>)

Four combinators [Adjacent Sibling(+), General Sibling(~), Child(>), Descendant( )]

When set CSS Styles, below syntax is a basic.

h1 {
  color:#FFFF11;
  background: #000000;
}

.subTitle {
  font-size:13px;
  color:#FFFFFF;
  font-family:inherit;
}

#timeLine {
  background:gray;
}

But when you want to set Styles to a specific tag, using combinators is a smart selection.

combinators are mixed Styles. like ‘div + h1’ or ‘div > span’.

Any tags are mixable and there are four combinator types.

  • Adjacent Sibling (+)
  • General Sibling (~)
  • Child (>)
  • Descendant ( space )

1. Adjacent Sibling (+)

Adjacent Sibling uses + mark when specifies one element right after designated element.

h1 + p {
  color:orange;
}

Result is shown below.

<div>
  <h1>I'm h1 tag</h1>
  <p>I'm orange</p>
  <h2>I'm h2 tag</h2>
  <p>I'm a second p tag</p>
  <h1>I'm h1 tag again</h1>
  <p>I'm orange too</p>
<div>

There are two conditions for adjacent sibling.

Element should share the same parent and second element has to come only if right after first element.

In the above HTML result, there are three <p> tag lines but only two lines are matched to the condition.

Therefore only two matched elements are working as mentioned.

2. General Sibling (~)

General Sibling uses ~ mark when specifies elements come after designated element.

h1 ~ p {
  color:orange;
}

Result is shown below.

<div>
  <h1>I'm h1 tag</h1>
  <p>I'm orange</p>
  <h2>I'm h2 tag</h2>
  <p>I'm orange too</p>
<div>

There are two conditions for general sibling.

Element should share the same parent and second element has to come after first element.

In the above HTML result, every <p> tag after <h1>tag is working.

3. Child (>)

Use > marks when express child elements.

div > p {
  color:orange;
}

Result is shown below.

<div>
  <h1>I'm just h1 tag</h1>
  <p> I'm colored orange</p>
  <span>
    <p>I'm not the one</p>
  </span>
  <p> I also am colored orange</p>
</div>

Second element has to be a direct child of first element.

In the above HTML result, only two direct child lines are working.

Fifth line is not working because its position is parent-child-child.

4. Descendant

Use space when express descendant elements.

div p {
  color:orange;
}

Result is shown below.

<div>
  <h1>I'm just h1 tag</h1>
  <p> I'm colored orange</p>
  <span>
    <p>Count me in</p>
  </span>
  <p> I also am colored orange</p>
</div>

As long as second element is a descendant of the first element, every matched line is working.


Combinators are easy and simple for efficient CSS work.

I hope this post is helpful to your CSS design.