"tac"를 사용하지 않고 파일에서 줄을 뒤로 인쇄하려면 어떻게해야합니까?


26

tac명령 을 사용하지 않고 파일에서 줄을 뒤로 인쇄하고 싶습니다 . bash로 그러한 일을하는 다른 해결책이 있습니까?


답변:


33

sed에뮬레이션을 사용 하여 tac:

sed '1!G;h;$!d' ${inputfile}

3
이것은 좋은 해결책이지만 이것이 어떻게 작동하는지에 대한 설명이 더 좋습니다.
Chen Levy

10
유명한 sed원 라이너입니다. "36. 라인의 역순 ("tac "Unix 명령 에뮬레이션)을 참조하십시오." 에서 유명한 Sed의 한 - 라이너 설명 그것이 작동하는 방법에 대한 자세한 설명.
Johnsyweb

6
"이 두 개의 단일 라이너는 실제로 전체 파일을 인쇄하기 전에 전체 버퍼를 역순으로 유지하기 때문에 많은 양의 메모리를 사용합니다. 큰 파일의 경우 이러한 단일 라이너를 피하십시오."
Mr. Shickadance

다른 모든 답변을 수행하십시오 (아마도 사용하지 않는 답변 sort-임시 파일을 사용할 가능성이 있습니다).
Random832

1
tac은 파일을 뒤로 읽기 때문에 일반 파일에 더 빠릅니다. 파이프의 경우 다른 솔루션 (메모리 또는 임시 파일에 보관)과 동일하게 수행해야하므로 훨씬 빠르지는 않습니다.
Stéphane Chazelas


6

awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file.txt

하나의 라이너 를 통해


4
더 짧은 것 :awk 'a=$0RS a{}END{printf a}'
ninjalj

@ninjalj : 더 짧을 수 있지만 파일 크기가 커질수록 속도 가 매우 느려집니다. 나는 2 분 30 초를 기다린 후 포기했다. but your first perl reverse <>`이 awk답변 보다 10 배 빠르며 페이지에서 가장 빠르거나 가장 빠른 답변입니다 (모든 aks anseres는 시간에 따라 거의 동일합니다)
Peter.O

1
또는awk '{a[NR]=$0} END {while (NR) print a[NR--]}'
Stéphane Chazelas

5

bash에서 요청한 것처럼 awk, sed 또는 perl을 사용하지 않고 bash 함수 만 사용하는 솔루션이 있습니다.

reverse ()
{
    local line
    if IFS= read -r line
    then
        reverse
        printf '%s\n' "$line"
    fi
}

의 출력

echo 'a
b
c
d
' | reverse

이다

d
c
b
a

예상대로.

그러나 행은 메모리에 저장되며 각 행마다 한 줄씩 함수 인스턴스라고합니다. 큰 파일을 조심하십시오.


1
파일 크기가 증가함에 따라 다른 응답 중 가장 느린 속도에 비해 빠르게 비실용적으로 느려집니다. 제안한 바와 같이 메모리를 매우 쉽게 날려 버립니다. * bash 재귀 함수 ...하지만 흥미로운 아이디어입니다. 분할 오류 *
Peter.O

4

다음을 통해 파이프 할 수 있습니다.

awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'

awk프리픽스는 행 번호와 각 행은 공백. 는 sort역순 숫자 스타일 첫번째 필드 (행 번호)에 의해 정렬 라인들의 순서를 반전. 그리고 sed줄 번호를 제거합니다.

다음 예제는이를 실제로 보여줍니다.

pax$ echo 'a
b
c
d
e
f
g
h
i
j
k
l' | awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'

출력합니다 :

l
k
j
i
h
g
f
e
d
c
b
a

승인. 감사! 나는 이것을 시도 할 것이다. 그리고 의견 감사합니다!

5
cat -n같은 행동awk '{print NR" "$0}'
첸 레비 11

2
나는라고 생각 찌언 변환 , 또는 장식 - 정렬 undecorate
ninjalj

이 일반적인 접근 방식은 작업이 메모리에서 합리적으로 수행하기에 너무 큰 경우 디스크의 파일을 사용하는 정렬 핸들에 유용합니다. 파이프 대신 단계간에 임시 파일을 사용한 경우 메모리가 더 부드럽습니다.
mc0e

1

펄에서 :

cat <somefile> | perl -e 'while(<>) { push @a, $_; } foreach (reverse(@a)) { print; }'

2
또는 더 짧은perl -e 'print reverse<>'
ninjalj

2
(사실, 짧은 하나가,하지만 그건 정말 증인의 무서움 추한 : perl -pe '$\=$_.$\}{')
ninjalj

@ Frederik Deweerdt : reverse<)빠르지 만 첫 번째 줄을 잃습니다 ... @ ninjalj : 빠릅니다 : 좋습니다! 그러나 "정말 못생긴"것은 줄의 수가 증가함에 따라 매우 느립니다 . !! ....
Peter.O

@ Peter.O는 -n거기에 불필요한 것이 었습니다. 감사합니다.
Frederik Deweerdt

이것에 대한 좋은 점은 파일의 내용이 반드시 메모리로 읽힐 필요는 없다는 것입니다 sort.
Kusalananda

0

BASH 전용 솔루션

bash 배열로 파일을 읽고 (한 줄 = array의 한 요소) 배열을 역순으로 인쇄하십시오.

i=0 

while read line[$i] ; do
    i=$(($i+1))
done < FILE


for (( i=${#line[@]}-1 ; i>=0 ; i-- )) ; do
    echo ${line[$i]}
done

들여 쓰기 한 줄로 시도해보십시오 ... philfr의 버전은 조금 나아지지만 여전히 veeeery slooooow이므로 텍스트 처리와 관련해서는 절대 사용하지 마십시오 while..read.
don_crissti

사용 IFS=''read -r탈출의 모든 종류의 방지를 망쳐에서 IFS 제거를 후행한다. bash mapfile ARRAY_NAME내장 기능이 배열을 읽는 데 더 나은 솔루션 이라고 생각합니다 .
Arthur2e5

0

Bash, mapfilefiximan에 대한 의견에 언급되었으며 실제로 더 나은 버전입니다.

# last [LINES=50]
_last_flush(){ BUF=("${BUF[@]:$(($1-LINES)):$1}"); } # flush the lines, can be slow.
last(){
  local LINES="${1:-10}" BUF
  ((LINES)) || return 2
  mapfile -C _last_flush -c $(( (LINES<5000) ? 5000 : LINES+5 )) BUF
  BUF=("${BUF[@]}") # Make sure the array subscripts make sence, can be slow.
  ((LINES="${#BUF[@]}" > LINES ? LINES : "${#BUF[@]}"))
  for ((i="${#BUF[@]}"; i>"${#BUF[@]}"-LINES; i--)); do echo -n "${BUF[i]}"; done
}

성능은 기본적으로 sed솔루션 과 비슷하며 요청 된 줄 수가 줄어들면 더 빨라집니다.


0
Simple do this with your file to sort the data in reverse order, and it should be unique.

sed -n '1h; 1d; G; h; $ p'


0
  • nl로 줄 번호 매기기
  • 번호를 역순으로 정렬
  • sed로 숫자를 제거하십시오

여기에 표시된대로 :

echo 'e
> f
> a
> c
> ' | nl | sort -nr | sed -r 's/^ *[0-9]+\t//'

결과:

c
a
f
e

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.