각 줄의 내용을 유지하면서 텍스트 파일 (또는 stdin)의 줄 순서를 바꾸고 싶습니다.
즉, 다음으로 시작하십시오.
foo
bar
baz
나는 끝내고 싶다
baz
bar
foo
이에 대한 표준 UNIX 명령 줄 유틸리티가 있습니까?
각 줄의 내용을 유지하면서 텍스트 파일 (또는 stdin)의 줄 순서를 바꾸고 싶습니다.
즉, 다음으로 시작하십시오.
foo
bar
baz
나는 끝내고 싶다
baz
bar
foo
이에 대한 표준 UNIX 명령 줄 유틸리티가 있습니까?
답변:
또한 언급 할 가치가 있습니다 : tac
(the, ahem, reverse of cat
). coreutils 의 일부 입니다.
tac a.txt > b.txt
brew install coreutils
( gtac
기본적으로 설치)를 사용하여 tac을 설치할 수 있습니다 .
echo -n "abc\ndee" > test; tac test
.
있다 잘 알려진 나오지 트릭 :
# reverse order of lines (emulates "tac")
# bug/feature in HHsed v1.5 causes blank lines to be deleted
sed '1!G;h;$!d' # method 1
sed -n '1!G;h;$p' # method 2
(설명 : 버퍼를 유지하기 위해 비 초기 라인 앞에 추가, 라인 교체 및 버퍼 유지, 끝에 라인 인쇄)
또는 awk one-liners에서 (빠른 실행으로) :
awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file*
기억이 안 나면
perl -e 'print reverse <>'
GNU 유틸리티를 갖춘 시스템에서 다른 대답은 더 간단하지만 전 세계가 GNU / Linux는 아닙니다 ...
tail -r
tac 은 사용할 수 없습니다 .
tac
메모리에 맞지 않는 임의의 큰 파일을 처리 할 것으로 예상됩니다 (행 길이는 여전히 제한됨). 해당 sed
파일에 대한 솔루션이 작동 하는지 확실하지 않습니다 .
명령이 끝나면 다음을 입력하십시오.
| tac
tac은 정확히 당신이 요구하는 것을 수행합니다. "각 줄을 표준 출력에 마지막 줄에 기록하십시오."
tac는 cat :-)의 반대입니다.
tac
명령 의 값을 설명하십시오 . 이는 동일한 주제를 검색하게 된 새로운 사용자에게 유용합니다.
당신은에 될 일 경우 vim
사용
:g/^/m0
$ (tac 2> /dev/null || tail -r)
tac
Linux에서 작동하는을 사용해보십시오 . 그래도 작동하지 않으면 tail -r
BSD 및 OSX에서 작동합니다.
tac myfile.txt
안되나요?
tail -r
경우에 대비 하여 tac
사용할 수 없습니다. tac
POSIX를 준수하지 않습니다. 둘 다입니다 tail -r
. 여전히 완벽한 것은 아니지만 이것은 작동하는 가능성을 향상시킵니다.
tac
사용 가능한 경우 에 발생 하지만 RAM이 부족하고 거대한 입력 스트림을 소비하여 절반을 교환합니다. 실패한 다음 tail -r
나머지 스트림 처리에 성공하여 잘못된 결과를 제공합니다.
brew install coreutils
사용 gtac
대신에 tac
그리고 만약 당신의 별칭으로 추가 전술을 선호 gtac
예를 들어 당신이 크로스 플랫폼 (리눅스, OSX)를 사용 쉘 스크립트 원하는 경우
다음 명령을 시도하십시오 :
grep -n "" myfile.txt | sort -r -n | gawk -F : "{ print $2 }"
sed 's/^[0-9]*://g'
nl
은 기본적으로 빈 줄에 번호를 매기 지 않습니다. 이 -ba
옵션은 보편적이지 않은 일부 시스템에서 사용할 수 있습니다 (HP / UX는 마음에 들지 않지만) (이 경우에는 비어 있음) 정규식과 일치하는 모든 줄에 grep -n
항상 번호를 매 깁니다.
cut -d: -f2-
그냥 배쉬 :) (4.0+)
function print_reversed {
local lines i
readarray -t lines
for (( i = ${#lines[@]}; i--; )); do
printf '%s\n' "${lines[i]}"
done
}
print_reversed < file
-nenenenenenene
하고 사람들이 printf '%s\n'
대신 항상 사용 하는 것이 좋습니다 이유를 목격하십시오 echo
.
가장 간단한 방법은 tac
명령을 사용하는 것 입니다. tac
이다 cat
의 역수. 예:
$ cat order.txt
roger shah
armin van buuren
fpga vhdl arduino c++ java gridgain
$ tac order.txt > inverted_file.txt
$ cat inverted_file.txt
fpga vhdl arduino c++ java gridgain
armin van buuren
roger shah
나는 " 꼬리 -r "답변을 정말 좋아 하지만 가장 좋아하는 gawk 답변은 ...입니다.
gawk '{ L[n++] = $0 }
END { while(n--)
print L[n] }' file
mawk
우분투 14.04 LTS에서 테스트되었습니다 -작동하므로 GNU awk에 국한되지 않습니다. +1
n++
NR
다음을 편집 하면 1에서 10 사이의 무작위로 정렬 된 숫자 목록이 생성됩니다.
seq 1 10 | sort -R | tee /tmp/lst |cat <(cat /tmp/lst) <(echo '-------') **...**
여기서 점은 목록을 반전시키는 실제 명령으로 대체됩니다.
전술
seq 1 10 | sort -R | tee /tmp/lst |cat <(cat /tmp/lst) <(echo '-------') \
<(tac)
파이썬 : sys.stdin에서 [::-1] 사용
seq 1 10 | sort -R | tee /tmp/lst |cat <(cat /tmp/lst) <(echo '-------') \
<(python -c "import sys; print(''.join(([line for line in sys.stdin])[::-1]))")
tac
쉘 스크립트 내부에서 사용할 수있는 교차 OS (예 : OSX, Linux) 솔루션의 경우 위에서 언급 한 것처럼 homebrew를 사용하고 다음과 같이 별칭 전술을 사용하십시오.
lib 설치
MacOS 용
brew install coreutils
리눅스 데비안
sudo apt-get update
sudo apt-get install coreutils
그런 다음 별칭을 추가하십시오.
echo "alias tac='gtac'" >> ~/.bash_aliases (or wherever you load aliases)
source ~/.bash_aliases
tac myfile.txt
n
매우 큰 텍스트 파일 의 마지막 줄을 효율적 으로 얻고 싶습니다 .
내가 시도한 첫 번째 방법은 tail -n 10000000 file.txt > ans.txt
이지만 매우 느리다는 것을 알았습니다. 왜냐하면 tail
위치를 찾은 다음 뒤로 이동하여 결과를 인쇄해야하기 때문입니다.
그것을 알게되면 다른 솔루션으로 전환합니다 tac file.txt | head -n 10000000 > ans.txt
. 이번에는 탐색 위치가 끝에서 원하는 위치로 이동하기 만하면 50 %의 시간이 절약됩니다 !
집에 메시지를 :
옵션 이없는 tac file.txt | head -n n
경우 사용하십시오 .tail
-r
나는 같은 질문을했지만 첫 번째 줄 (헤더)이 맨 위에 머물기를 원했습니다. 그래서 awk의 힘을 사용해야했습니다
cat dax-weekly.csv | awk '1 { last = NR; line[last] = $0; } END { print line[1]; for (i = last; i > 1; i--) { print line[i]; } }'
PS는 cygwin 또는 gitbash에서도 작동합니다.
1\n20\n19...2\n
그보다 는 오히려 결과로 나타납니다 20\n19...\2\n1\n
.
당신은 그것을 할 수 vim
stdin
와 stdout
. 당신은 또한 사용할 수 있습니다 ex
로 POSIX를 준수 . vim
에 대한 시각적 모드입니다 ex
. 실제로 또는 (개선 된 모드) ex
와 함께 사용할 수 있습니다 .
같은 도구와 달리 편집을 위해 파일을 버퍼링하고 스트림에 사용 되기 때문에 유용 합니다. 을 사용할 수 있지만 변수의 모든 항목을 수동으로 버퍼링해야합니다.vim -e
vim -E
ex
vim
sed
sed
awk
아이디어는 다음을 수행하는 것입니다.
g/^/m0
입니다. 이것은 각 라인에 대해 전 세계적으로 의미합니다 g
. 줄의 시작과 일치합니다 ^
. 주소 1 (1 행) 다음으로 이동하십시오 m0
.%p
입니다. 이것은 모든 라인의 범위를 의미합니다 %
. 선을 인쇄하십시오 p
.q!
입니다. 이것은 종료를 의미합니다 q
. 강력하게 !
.# Generate a newline delimited sequence of 1 to 10
$ seq 10
1
2
3
4
5
6
7
8
9
10
# Use - to read from stdin.
# vim has a delay and annoying 'Vim: Reading from stdin...' output
# if you use - to read from stdin. Use --not-a-term to hide output.
# --not-a-term requires vim 8.0.1308 (Nov 2017)
# Use -E for improved ex mode. -e would work here too since I'm not
# using any improved ex mode features.
# each of the commands I explained above are specified with a + sign
# and are run sequentially.
$ seq 10 | vim - --not-a-term -Es +'g/^/m0' +'%p' +'q!'
10
9
8
7
6
5
4
3
2
1
# non improved ex mode works here too, -e.
$ seq 10 | vim - --not-a-term -es +'g/^/m0' +'%p' +'q!'
# If you don't have --not-a-term, use /dev/stdin
seq 10 | vim -E +'g/^/m0' +'%p' +'q!' /dev/stdin
# POSIX compliant (maybe)
# POSIX compliant ex doesn't allow using + sign to specify commands.
# It also might not allow running multiple commands sequentially.
# The docs say "Implementations may support more than a single -c"
# If yours does support multiple -c
$ seq 10 | ex -c "execute -c 'g/^/m0' -c '%p' -c 'q!' /dev/stdin
# If not, you can chain them with the bar, |. This is same as shell
# piping. It's more like shell semi-colon, ;.
# The g command consumes the |, so you can use execute to prevent that.
# Not sure if execute and | is POSIX compliant.
seq 10 | ex -c "execute 'g/^/m0' | %p | q!" /dev/stdin
이것을 재사용 할 수있게 만드는 방법
ved
vim sed
을 사용하여 편집 할 스크립트 (예 : vim editor )를 사용 stdin
합니다. 이것을 ved
경로 에있는 파일에 추가하십시오 :
#!/usr/bin/env sh
vim - --not-a-term -Es "$@" +'%p | q!'
vim이 10 개의 명령으로 제한하기 때문에, +
대신 하나의 명령을 사용하고 +'%p' +'q!'
있습니다. 따라서 그것들을 병합하면 8 대신 "$@"
9 개의 +
명령 을 가질 수 있습니다 .
그럼 당신은 할 수 있습니다 :
seq 10 | ved +'g/^/m0'
vim 8이 없다면 ved
대신 이것을 넣으십시오 :
#!/usr/bin/env sh
vim -E "$@" +'%p | q!' /dev/stdin
rev
text here
또는
rev <file>
또는
rev texthere
sort -r < filename
또는
rev < filename
sort -r
입력이 이미 정렬 된 경우에만 작동하지만 여기에는 해당되지 않습니다. rev
줄당 문자를 바꾸지 만 줄 순서는 그대로 유지합니다. 이는 Scotty가 요청한 내용이 아닙니다. 따라서이 답변은 실제로 전혀 답이 아닙니다.
perl -e 'print reverse <>'
하지만 다른 방법에도 적용됨).