2018년 12월 25일 화요일

남녀의 생물학적 차이로 가져 오는 결과

조던 피터슨의 글에 대해서 반박하는 유튜브 동영상을 보고 정리 해보았습니다.

요즘 유튜브에서 갑론을박입니다. 이런 소재의 이야기를 하는 사람이 많습니다. 서로 반박하는 영상 올리고 무엇이 주장합니다. 아무래도 조만간에 대토론회 열어서 진행되는걸 보고 싶네요. 결론 내기는 힘들지라도 일반 사람들이 판단하는데 도움은 될 것 같습니다.


얼굴은 가렸네요. 대부분 얼굴 가리고 진행하는 사람이 많습니다. 일단 남녀의 차이를 과학적인 부분은 인정하는 내용입니다.


M포인트가 뭔지 P포인트가 뭔지 자세히 설명도 해줍니다. 이 내용은 어느 정도 다들 아시는 내용입니다.


일반적으로 반대로 적용되는 비율을 보여줍니다. 17% 정도가 다르게 적용된다고 하네요. 남자든 여자든 트랜스젠더도 있고 동성애도 있고 그러니 절대적으로 적용되지 않는다라는 건 이해됩니다.


역사적으로 하나씩 따져보면서 설명해줍니다. 설명은 요약이 무엇이냐면 생물학적으로 결정된 선천적인 것보다 후천적인 것이 더 중요하다라고 이야기 합니다. 그 후척적에는 교육이라는 요소가 큰 영향을 미친다고 합니다. 다만 현재 리더급이라고 말하는 사람들 중 남자가 많은 비중을 차지하는 것이 능력보다는 정치질 때문이라고 합니다.
그 정치질에는 많은 부분이 내포되어 있겠지요. 그럼 앞으로는? 어떻게 되는 것일까요?


결론은 현재는 과거와 달리 여성들이 교육 수준이 높아져서 후천적 계발이 되어 있으니 생물학적 차이가 중요하지 않다고 합니다. 그래서 여성이 리더급으로 많은 비율을 차지 할 것이라고 합니다.

영상 잘 보았습니다? 이 영상은 생물학적 차이만 반박하는 내용만 담았네요.

2018년 12월 24일 월요일

조던 피터슨 스칸디나비아에서 토크쇼

조던 피터슨이 어떤 사람인지?


나무 위키에서 간략하게 찾아 보면

캐나다의 임상 심리학자이자 문화 비평가. 2018년 현재 토론토 대학교의 심리학과 교수로 재직하고 있다. 
주된 연구 분야는 사회심리학, 성격심리학 등이며, 특히 인간이 종교나 이데올로기를 믿게 되는 심리적 원인, 개인의 성취를 향상시키는 방법, 반사회적 행동의 교정법 등에 업적을 남겼다. 출신 학교는 캐나다의 알버타 대학교(학부)와 맥길 대학교(대학원)로, 박사 학위 취득 후 맥길 대학교에 2년간 더 연구원으로 남아있다가, 1993년에 하버드 대학교의 심리학과 교수로 임용되었다. 하버드에서 5년간 교수로 재직한 뒤에 1998년 토론토 대학교의 전임교수가 되어 캐나다로 돌아왔다.

쉽게 말하면 학자입니다. 이때까지 이런 저런 사회적인 발언을 많이 해왔으며 현재는 페미니스트와 토론을 많이 하는 것 같습니다. 유튜브에서 조던 피턴슨이라고 찾으면 동영상이 많이 뜹니다. 대부분이 페미니스트와 논쟁입니다.



최근에 나온 모습입니다. 순간 보면 꼰대 같은 느낌이 듭니다. ㅎㅎㅎ 그래서 이 사람의 주장을 듣고 생각해야 겠지요.


엄청 자유 분방하게 진행이 됩니다. 진행하면서 보면 1:3으로 진행되는 느낌입니다. 그리고 진행 같은 룰이나 이런 것도 없어 보이고 그냥 거침없이 생각을 주고 받습니다.





위에 이야기가 가장 근본적인 핵심인 것 같습니다. 남녀의 차이는 두가지인데 첫째는 문화이고 둘째는 생물학적 차이라고 이야기합니다. 그리고 문화적 차이를 최소화하면 생물학적 차이가 최대화 된다고 합니다. 이미 과학계에서 최소 25년전부터 알고 있던 것이라고 합니다.

문화적 차이는 시대와 장소에 따라서 달라지고 있습니다. 하지만 생물학적 차이는 달라지고 있지 않고 있습니다. 페미니스트에 가장 의견의 차이는 남자 여자의 생물학적 차이를 어디까지 서로 이해하고 합의할 수 있을지 궁금합니다.



다음은 기회의 평등(기회균등)이라는 말은 많이 들어 보았습니다. 그리고 사회적 약자에게 기회를 좀 주는 걸 우리는 복지라고 생각할 수 있습니다. 하지만 결과의 평등은 처음 듣습니다.

결과의 평등이 적용이 가능한 곳이 있는지 궁금합니다. 실제적으로 여기서도 결과의 평등에 대해서는 긍정적이지 않고 잠깐 부정적으로 언급했던 것 같습니다.

조수애 아나운서 결혼이 왜?

조수애 아나운서는 1992년 생입니다. 2016년 1월부터 JTBC 아나운서가 되었습니다. 전 팬도 아니고 그냥 바로 내용을 짚어 보도록 하겠습니다.


말말말

히든싱어5 9회 바다편을 먼저 살펴 보겠습니다.







히든싱어5는 예능입니다. 그리고 원조가수가 어디에 있는지 맞추는 것입니다. 현재 2라운드가 진행 되고 있고 가수 바다가 가장 아닐 것 같은 곳에 번호를 누르는 것입니다.

조수애는 3번을 선택하였고 왜 그렇게 생각하는지 자신의 의견을 이야기했습니다. 무엇이 문제인지 모르겠지만 이것이 논란이 됩니다.

언론에서 난리가 났습니다. 왜 그런 것이죠? 제 생각엔 아무 일도 아닌 것을 일을 만드는 듯 합니다.

양세찬의 텐2 10회




아 크기 맞추기 아직 서툴어서 힘드네요. 아무튼 여기서 남자친구가 없듯이 이야기합니다. 이상형은 친구처럼 지낼 수 있는 사람이라고 밝혔습니다. 큰 문제가 될 내용은 전혀 아닙니다. 남자 친구가 있든 없든 자신이 명확하게 밝힌 필요는 없다고 생각합니다. 이상형과 결혼 한다라는 보장도 없습니다.

하지만 8일에 결혼 문제에 대해서 엄청나게 말이 많습니다.


8일 두산매거진 박서원 대표와 결혼식을 올렸다고 합니다. 1992년생인 조수애는 올해 27세, 1979년생인 박서원 대표의 나이는 40세로 두 사람은 13살 나이차이가 납니다. 박서원 대표가 이혼남이고 나이 많은데 조수애와 결혼 하는 것은 단지 돈때문이라고 생각해서 그런 듯 합니다.

돈때문에 결혼하면 안되는 이유가 무엇입니까? 궁금합니다. 물론 자신은 돈보다는 다른 부분을 더 중요하다고 생각하는 사람도 많을 것입니다. 다시 말해 결혼 하는 이유는 사람마다 생각이 다를 것입니다. 하지만 자신의 생각과 다르다고 그리고 악성댓글을 달 필요는 없습니다.

2018년 11월 15일 목요일

std::set 간단 사용 예제


#include <iostream>
#include <set>
#include <functional>

void Result(std::pair<std::set<int>::iterator, bool> * p) {
    if (true == p->second)
        cout << *p->first << " Insert success!" << endl;
    else
        cout << *p->first << " is Exist. Insert Fail! " << endl;
}

int main(){

    std::set<int> s;

    std::pair<std::set<int>::iterator, bool> ins1, ins2;
    ins1 = s.insert(50);
    s.insert(40);
    s.insert(80);
    ins2 = s.insert(40);

    Result(&ins1);
    Result(&ins2);

    std::set<int>::iterator iter;
    for (iter = s.begin(); iter != s.end(); ++iter){
        cout << *iter << " ";
    }

}

output
50 Insert success!
40 is Exist. Insert Fail! 
40 50 80 

std::set 은 유일한 값(키)이 들어 가며 자동정렬이 된다. std::map  은 key 와 value 이지만 std::set 는 key 만 존재한다. 이걸 사용하는 곳은 흔치 않지만 알아두면 간혹 적절하게 사용할 시점이 발견된다.

2018년 11월 1일 목요일

[c++] array reverse

#include <stdio.h>
#include <stdlib.h>
#include <cstdlib>
#include <ctime>

#define NUMBER_COUNT 5

int main()
{
	int a[NUMBER_COUNT], i, temp, half_cnt = NUMBER_COUNT / 2;

    srand((unsigned int)time(NULL));

	for(i=0;i<NUMBER_COUNT;i++){
		a[i] = rand() % 100 + 1;
		printf("%d ",a[i]);
	}
	printf("\n");

	for(i=0; i<half_cnt ;i++){
		temp = a[i];
		a[i] = a[NUMBER_COUNT-i-1];
		a[NUMBER_COUNT-i-1] = temp;
		a[NUMBER_COUNT-i-1] = temp;
	}

	for(i=0;i<NUMBER_COUNT;i++){
		printf("%d ",a[i]);
	}
	
	printf("\n");
	system("pause");

	return 0;

}

위 소스를 보면 NUMBER_COUNT 로 개수를 미리 셋팅합니다. 그리고 돌려 보면 미리 랜덤하게 생성된 값을 보여주고 그리고 바로 밑에 서로 자리를 바꾼 값을 보여줍니다.

바꾸는 방법은 양끝에 있는 것을 서로 자리를 바꾸는 방식으로 하였습니다. 그래서 반복문은 전체 수에서 절반(버림) 만큼 반복합니다.

2018년 10월 31일 수요일

[C#] Dictionary Example

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Dictionary dictionary = new Dictionary();

        dictionary.Add("cat", 2);
        dictionary.Add("dog", 1);
        dictionary.Add("llama", 0);
        dictionary.Add("iguana", -1);
    }
}

using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var values = new Dictionary();
        values.Add("A", "uppercase letter A");
        values.Add("c", "lowercase letter C");

        // Use inline "out string" with TryGetValue.
        if (values.TryGetValue("c", out string description))
        {
            System.Console.WriteLine(description);
        }
    }
}

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // Example Dictionary again.
        Dictionary d = new Dictionary()
        {
            {"cat", 2},
            {"dog", 1},
            {"llama", 0},
            {"iguana", -1}
        };
        // Loop over pairs with foreach.
        foreach (KeyValuePair pair in d)
        {
            Console.WriteLine("{0}, {1}", pair.Key, pair.Value);
        }
        // Use var keyword to enumerate dictionary.
        foreach (var pair in d)
        {
            Console.WriteLine("{0}, {1}", pair.Key, pair.Value);
        }
    }
}

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Dictionary d = new Dictionary()
        {
            {"cat", 2},
            {"dog", 1},
            {"llama", 0},
            {"iguana", -1}
        };
        // Store keys in a List.
        List list = new List(d.Keys);
        // Loop through list.
        foreach (string k in list)
        {
            Console.WriteLine("{0}, {1}", k, d[k]);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Diagnostics;

class Program
{
    static void Main()
    {
        var test = new Dictionary();
        test["bird"] = 10;
        test["frog"] = 20;
        test["cat"] = 60;
        int sum = 0;
        const int _max = 1000000;

        // Version 1: use foreach loop directly on Dictionary.
        var s1 = Stopwatch.StartNew();
        for (int i = 0; i < _max; i++)
        {
            foreach (var pair in test)
            {
                sum += pair.Value;
            }
        }
        s1.Stop();

        // Version 2: use foreach loop on Keys, then access values.
        var s2 = Stopwatch.StartNew();
        for (int i = 0; i < _max; i++)
        {
            foreach (var key in test.Keys)
            {
                sum += test[key];
            }
        }
        s2.Stop();
        Console.WriteLine(s1.Elapsed.TotalMilliseconds);
        Console.WriteLine(s2.Elapsed.TotalMilliseconds);
    }
}

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        // Use a Dictionary with an int key.
        Dictionary dict = new Dictionary();
        dict.Add(100, "Bill");
        dict.Add(200, "Steve");
        // We can look up the int in the Dictionary.
        if (dict.ContainsKey(200))
        {
            Console.WriteLine(true);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        string[] arr = new string[]
        {
            "One",
            "Two"
        };
        var dict = arr.ToDictionary(item => item, item => true);
        foreach (var pair in dict)
        {
            Console.WriteLine("{0}, {1}",
                pair.Key,
                pair.Value);
        }
    }
}

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Dictionary d = new Dictionary();
        d.Add("cat", 1);
        d.Add("dog", 2);
        if (d.ContainsValue(1))
        {
            Console.WriteLine(true); // True.
        }
    }
}

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Dictionary dictionary = new Dictionary();

        // We can assign with the indexer.
        dictionary[1] = 2;
        dictionary[2] = 1;
        dictionary[1] = 3; // Reassign.

        // Read with the indexer.
        // ... An exception occurs if no element exists.
        Console.WriteLine(dictionary[1]);
        Console.WriteLine(dictionary[2]);
    }
}

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Dictionary d = new Dictionary();
        d.Add("cat", 1);
        d.Add("dog", 2);

        d.Remove("cat"); // Removes cat.
        d.Remove("nothing"); // Doesn't remove anything.
    }
}

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Example e = new Example();
        Console.WriteLine(e.GetValue());
    }
}

class Example
{
    Dictionary _d = new Dictionary()
    {
        {1, 1},
        {2, 3},
        {3, 5},
        {6, 10}
    };
    public int GetValue()
    {
        return _d[2]; // Example only.
    }
}

2018년 10월 30일 화요일

[c++] 문자를 숫자로 바꾸는 방법들

프로그램 하다 보면 변환에 대해서 찾아 보는 경우가 많죠.


//case 1
int a = 10;
char *intStr = itoa(a);
std::string str = std::string(intStr);


//case 2
int a = 10;
std::stringstream ss;
ss << a;
std::string str = ss.str();

//case 3
std::string s = std::to_string(42);
std::string s = std::to_stoi(42);


위 세가지 방법중 편한걸 사용하시면 됩니다.

2018년 10월 29일 월요일

std::random_shuffle, std::shuffle

예전에 처리했던 방법
처음부터 순회하면서 랜덤한 위치의 값과 바꾼다.

void Shuffle(int * index, int nMax)
{
int i, n;
int tmp;

for (i=nMax-1;i>=0;i--)
{
n = rand() % nMax;
tmp = index[i];
index[i] = index[n];
index[n] = tmp;
}
}


요즘은 아래와 같이 코딩으로 처리한다.

#include <random>
#include <algorithm>
#include <iterator>
#include <iostream>

int main()
{
    std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    std::random_device rd;
    std::mt19937 g(rd());

    std::shuffle(v.begin(), v.end(), g);

    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << "\n";
}

Result :
10 6 8 7 2 3 4 9 5 1


자세한 내용과 다른 방법을 알고 싶으면 아래를 살펴 보면 된다.

Defined in header <algorithm>

template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last );

template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc& r );


template< class RandomIt, class RandomFunc >
void random_shuffle( RandomIt first, RandomIt last, RandomFunc&& r );


template< class RandomIt, class URBG >
void shuffle( RandomIt first, RandomIt last, URBG&& g );




내부적으로 처리 방법을 보면 특별하지 않다. 이미 익히 알고 있는 방법과 다르지 않다.

template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last )
{
    typename std::iterator_traits<RandomIt>::difference_type i, n;
    n = last - first;
    for (i = n-1; i > 0; --i) {
        using std::swap;
        swap(first[i], first[std::rand() % (i+1)]);
    }
}

template<class RandomIt, class RandomFunc>
void random_shuffle(RandomIt first, RandomIt last, RandomFunc&& r)
{
    typename std::iterator_traits<RandomIt>::difference_type i, n;
    n = last - first;
    for (i = n-1; i > 0; --i) {
        using std::swap;
        swap(first[i], first[r(i+1)]);
    }
}


template<class RandomIt, class URBG>
void shuffle(RandomIt first, RandomIt last, URBG&& g)
{
    typedef typename std::iterator_traits<RandomIt>::difference_type diff_t;
    typedef std::uniform_int_distribution<diff_t> distr_t;
    typedef typename distr_t::param_type param_t;
 
    distr_t D;
    diff_t n = last - first;
    for (diff_t i = n-1; i > 0; --i) {
        using std::swap;
        swap(first[i], first[D(g, param_t(0, i))]);
    }
}

PHP 활성화 하기

PHP 활성화 하기

1. php 활성화를 위해 아파치 설정파일을 연다.
sudo nano /etc/apache2/httpd.conf

2. LoadModule php5_module 이란 글로 시작하는 부분을 찾아서 # 을 제거해준다.
3. 아파치를 재시작한다.
4. 테스트 php 파일을 작성해서 테스트 해보자.
index.php
<?php phpinfo(); ?> 

index.php 경우 아래와 같은 경고 문고 뜨면
PHP Warning: phpinfo(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Asia/Seoul' for 'KST/9.0/no DST' instead in /usr/share/doc/squirrelmail-1.4.22/phpinfo.php on line 2

date.timezone = ## 변경 전
date.timezone = Asia/Seoul ## 변경 후
date.timezone = Asia/Seoul ## 변경 후

리눅스 vi 명령어

vi로 일을 불러온 직후의 상로, 입력 모드에서는 [esc] 를 를 시 진입한다. 

0. vi 기본

명령 모드

입력 모드에서 명령 모드로 다시 전환하려면 Esc 키를 누르기만 하면 됩니다. ESC 키를 누르고 문자를 입력하려고 하면 비프음만 날 뿐 입력은 되지 않을 것입니다. 
리눅스에서는 명령모드가 따로 있습니다. 명령모드는 편집모드라고도 하는데, 글을 입력시키는 방법이 아닌 수정과 편집을 할 수 있는 상태임을 기억해 두어야 합니다. 즉, 명령모드에서는 복사,삭제, 붙이기. . .등의 작업이 이루어 집니다. 또한, 입력모드를 통해 삽입 등 잘못된 명령을 내렸을 때 'u'라는 명령어를 통해서 Undo, 즉 복구가 가능하게 할 수 있습니다. 

콜론 모드

명령모드에서 콜론 모드로 전환하려면 ':'명령을 실행시키면 됩니다. 콜론 모드는 vi에서 사용할 수 있는 명령어들을 이용하는 곳입니다. 윈도우 환경에서라면 메뉴 바와 같은 역할을 한다고 볼 수 있습니다. 파일을 저장하거나 vi를 종료하는 등의 일을 수행할 수 있습니다. 콜론 모드로 들어가려면 Esc를 누른 후 ":"를 누르면 됩니다. 콜론 모드에 들어가게 되면 화면 아래쪽에 ':' 표시가 나타나게 되며, 여기서 원하는 작업에 해당하는 명령을 입력하고 Enter 키를 치면 됩니다. 아래 그림에서 아래쪽에 ":wq"라는 표시가 눈에 뜨일 것입니다. ":" 이 상태가 바로 앞에서 말한 콜론모드의 형태입니다. 

1. vi 실행하기

셀상에서 vi [파일명]를 입력하면 새로운 문서를 편집할 수 있는 환경이 만들어 집니다. 

명령어 동작 
vi file file을 연다 
vi file1 file2file1 과 file2 를 차례로 연다 
view file file을 읽기 모드로 연다 
vi -R file file을 읽기 모드로 연다 
vi + filefile을 열때 커서가 file 본문의 마지막 행에 위치한다. 
vi +n file file을 열어 n행에 위치한다. 
vi -r file손상된 파일 회복


2. 입력모드 전환 명령어

글자를 입력하기 위해서는 입력모드로 가야하는데, 'i'를 입력하면, 하단에 --INSERT--가 나오면서, 글자를 입력할 수 있는 
입력모드로 바뀝니다. 
입력 모드로 들어가는 대표적인 방법은 i 키를 누르는 것이지만, 이외에도 몇 가지 방법이 더 있습니다. 

명령어 동작 
커서 있는데서 입력모드 전환 
I커서 왼쪽, 행의 처음에 몬자 삽입 
커서 있는 줄 끝에서 입력모드 전환 
A커서 오른쪽, 행의 끝에 문자 삽입 
커서 있는 줄 아래에 빈 줄 삽입 
커서 있는 줄 위에 빈 줄을 삽입 
덮어쓰기 모드로 전환 


3. 커서의 이동

명령모드 상태에서 커서를 마음대로 움직일 수 있습니다. 

명령어 동작 
^, 0 줄의 처음으로 이동 
줄의 끝으로 이동 
H 화면 맨 위로 이동 
M화면의 중간으로 이동 
화면 맨 아래로 이동 
다음 단어 끝으로 커서 이동 
e다음 단어 앞으로 커서 이동
b  이전 단어로 이동 
shift + ↑ 한 페이지 앞으로 이동 
shift + ↓한 페이지 뒤로 이동 
3l , 3G현재 커서 위치한 행에서 3번째 행으로 이동 
Ctrl + i한 화면 위로 이동 
Ctrl + b한 화면 아래로 이동 
Ctrl + d반 화면 위로 이동 
Ctrl + u반 화면 아래로 이동 
Ctrl + e한 줄씩 위로 이동 
Ctrl + y한 줄씩 아래로 이동 


4. 삭제

명령어 동작 
한 문자 삭제 
5x커서가 있는 위치부터 5개의 문자를 삭제 
d + ↑ 커서있는 줄, 윗줄 2줄 삭제 
d + ↓ 커서잇는 줄, 아래줄 2줄 삭제 
dw 한 단어 삭제 
dd 한 줄 삭제 
5dd커서가 있는 라인부터 5개의 라인 삭제 
db커서의 위치에서 거꾸로 한 단어 삭제 
한줄 내에서 커서있는 뒤 모두 삭제 
바로 전에 수행한 명령을 취소 
:5,10ㅇ5~10번째 행 삭제 


5. 복사와 붙여넣기

명령어동작
yy현재 줄을 버퍼로 복사 
버퍼에 있는 내용을 커서 뒤에 삽입 
P버퍼에 있는 내용을 커서 앞에 삽입 
3y 현재 줄에서부터 아래로 3줄 복사 
:5, 10y5~10줄을 버퍼로 복사 
:30pu30행에 버퍼 내용을 삽입 
현재 커서가 위치해 있는 단어 복사 
3yy현재 행을 기준으로 3번째 행까지 n행 복사 


6. 문자열 찾기

명령어동작
/namename 문자열 찾기 
n다음 name으로 이동
Nn과 같으며 역방향으로 이동 


7. 문자열 대체

명령어 동작 
:s/str/rep현재 행의 str을 rep로 대체
:l,.s/str/rep/ 1부터 현재 행의 str을 rep로 대체 
:%s/str/rep/g 파일 전체 str을 rep로 전부 대체 
:.$/aaa/bbb커서의 위치로부터 파일의 끝까지 있는 모든 aaa를 bbb로 대체 


8. 파일 저장 및 불러오기

종료 명령은 앞에서 잠깐 콜론 모드에서 이루어 집니다. 
편집한 데이터를 저장하고 종료하려면, wq(Write and Quit)를 입력합니다. 

명령어 동작 
:w 지정된 파일에 저장 
:wq, :x, ZZ 지정된 파일에 저장하고 vi를 종료 
:w php.ini php.ini 파일에 저장 
 :q저장하지 않고 종료 
:q!저장하지 않고 강제 종료 
:wq php.ini php.ini에 저장하고 vi를 종료 
:r php.ini php.ini의 내용을 현재 커서가 있는데로 불러온다. 
:e php.ini 현재의 화면을 지우고 새로운 파일 php.ini를 불러온다. 
:5,10 w php.ini 5~10 줄까지의 내용을 php.ini에 저장


9. 기타

명령어 동작 
:set nu행 번호 보여주기 
:set nonu 행 번호 보여주기 취소 
 .바로 전에 실행한 명령어 재 실행 
 Ctrl + l불필요한 화면 정리후 다시 표시