[unix] .bash_history에서 중복을 제거하고 순서를 유지하려면 어떻게해야합니까?

나는 control+r내 명령 기록을 재귀 적으로 검색하기 위해 사용 하는 것을 정말로 좋아 합니다. 함께 사용하기에 좋은 몇 가지 옵션을 찾았습니다.

# ignore duplicate commands, ignore commands starting with a space
export HISTCONTROL=erasedups:ignorespace

# keep the last 5000 entries
export HISTSIZE=5000

# append to the history instead of overwriting (good for multiple connections)
shopt -s histappend

나에게 유일한 문제는 erasedups순차적 복제 만 지우는 것이므로이 명령 문자열을 사용하면됩니다.

ls
cd ~
ls

ls명령은 실제로 두 번 기록됩니다. 나는 cron을 주기적으로 실행하는 것에 대해 생각했습니다.

cat .bash_history | sort | uniq > temp.txt
mv temp.txt .bash_history

이렇게하면 복제본을 제거 할 수 있지만 불행히도 순서는 유지되지 않습니다. 내가하지 않으면 sort파일을 처음 나는 생각하지 않는다 uniq제대로 작동 할 수 있습니다.

.bash_history에서 중복을 제거하고 순서를 유지하려면 어떻게해야합니까?

추가 크레딧 :

.bash_history스크립트를 통해 파일을 덮어 쓰는 데 문제가 있습니까? 예를 들어, 아파치 로그 파일을 제거하면 파일에 kill연결하기 위해 nohup / reset 신호를 보내야한다고 생각 합니다. .bash_history파일 의 경우 ps필터링 스크립트를 실행하기 전에 연결된 세션이 없는지 확인하고 확인 하는 데 사용할 수 있습니까?



답변

역사 정렬

이 명령은처럼 작동 sort|uniq하지만 줄을 그대로 유지합니다

nl|sort -k 2|uniq -f 1|sort -n|cut -f 2

기본적으로 각 줄 앞에 숫자가 붙습니다. sort|uniq-ing 후 , 모든 행은 원래 순서에 따라 정렬되며 (행 번호 필드 사용) 행 번호 필드는 행에서 제거됩니다.

이 솔루션에는 정의 된 동일한 라인 클래스를 나타내는 결과가 출력에서 ​​만들어 지므로 최종 출력에서의 위치가 정의되지 않은 결함이 있습니다. 그러나 최신 담당자를 선택해야 할 sort경우 두 번째 키로 입력 할 수 있습니다 .

nl|sort -k2 -k 1,1nr|uniq -f1|sort -n|cut -f2

.bash_history 관리

다시 읽기와 역사를 다시 쓰기 위해, 당신은 사용할 수 있습니다 history -ahistory -w각각.


답변

그래서 나는 중복에 의해 성가신 후 똑같은 것을 찾고 있었고 ~ / .bash_profile (Mac)을 다음과 같이 편집하면 :

export HISTCONTROL=ignoreboth:erasedups

정확히 원하는 것을 수행하고 최신 명령 만 유지합니다. ignoreboth실제로하는 것과 같습니다. ignorespace:ignoredups그와 함께 erasedups작업을 수행합니다.

적어도 내 맥 터미널에서 bash가 완벽하게 작동합니다. 여기 askubuntu.com 에서 찾았습니다 .


답변

이 솔루션을 야생에서 발견하고 테스트했습니다.

awk '!x[$0]++'

라인의 특정 값 ($ 0)을 처음 볼 때 x [$ 0]의 값은 0입니다.
0의 값은 거꾸로되어 !1이됩니다.
1로 평가되는 명령문은 기본 조치 (인쇄)를 유발합니다.

따라서 특정 내용을 처음 $0볼 때 인쇄됩니다.

다음에 (반복 할 때마다) 값 x[$0]이 오름차순이고
, 부정 된 값은 0이며, 0으로 평가되는 명령문은 인쇄되지 않습니다.

마지막으로 반복되는 값을 유지하려면 기록을 되돌리고 동일한 awk를 사용하십시오.

awk '!x[$0]++' ~/.bash_history                 # keep the first value repeated.

tac ~/.bash_history | awk '!x[$0]++' | tac     # keep the last.


답변

Clayton 답변 연장 :

tac $HISTFILE | awk '!x[$0]++' | tac | sponge $HISTFILE

tac당신이 설치되어 있는지 확인, 파일을 역 moreutils당신이 그래서 sponge그렇지 않으면 임시 파일을 사용 가능합니다.


답변

이것들은 마지막으로 복제 된 줄을 유지합니다.

ruby -i -e 'puts readlines.reverse.uniq.reverse' ~/.bash_history
tac ~/.bash_history | awk '!a[$0]++' | tac > t; mv t ~/.bash_history


답변

이 게시물은 오래된 게시물이지만 여러 터미널을 열어두고 내역을 창 사이에 동기화했지만 복제하지 않은 사용자에게는 영원한 문제입니다.

.bashrc의 내 솔루션 :

shopt -s histappend
export HISTCONTROL=ignoreboth:erasedups
export PROMPT_COMMAND="history -n; history -w; history -c; history -r"
tac "$HISTFILE" | awk '!x[$0]++' > /tmp/tmpfile  &&
                tac /tmp/tmpfile > "$HISTFILE"
rm /tmp/tmpfile
  • histappend 옵션은 버퍼 히스토리를 히스토리 파일의 끝에 추가합니다 ($ HISTFILE)
  • ignoreboth 및 erasedups는 중복 항목이 $ HISTFILE에 저장되지 않도록합니다.
  • prompt 명령은 히스토리 캐시를 업데이트합니다
    • history -n 마지막 캐리지 리턴 이후 다른 터미널에서 발생했을 수있는 $ HISTFILE에서 모든 행을 읽습니다.
    • history -w 업데이트 된 버퍼를 $ HISTFILE에 씁니다.
    • history -c 중복이 발생하지 않도록 버퍼를 지 웁니다.
    • history -r 이제 빈 버퍼에 추가하여 $ HISTFILE을 다시 읽습니다.
  • awk 스크립트는 처음 발견 된 각 행을 저장합니다. tac역사상 가장 최근의 명령으로 저장할 수 있도록 역순으로 되 돌린 후 역순으로
  • rm / tmp 파일

새 쉘을 열 때마다 내역이 모두 지워지고 Enter다른 쉘 / 터미널 창에서 키를 누를 때마다 파일에서이 내역이 업데이트됩니다.


답변

모든 새로운 명령을 확실하게 기록하는 것은 까다 롭습니다. 먼저 다음을 추가 ~/.profile하거나 유사하게 해야합니다
.

HISTCONTROL=erasedups
PROMPT_COMMAND='history -w'

그런 다음에 추가해야합니다 ~/.bash_logout.

history -a
history -w