여러 개의 "sed" 명령(";"로 구분)을 실행하는 방법과 마찬가지로 "awk -F"를 사용하여 이를 수행할 수 있습니까? 여러 "awk"에서는 작동하지만 "awk-F"에서는 작동하지 않습니다.

여러 개의 "sed" 명령(";"로 구분)을 실행하는 방법과 마찬가지로 "awk -F"를 사용하여 이를 수행할 수 있습니까? 여러 "awk"에서는 작동하지만 "awk-F"에서는 작동하지 않습니다.

여러 파이프를 사용하지 않고 sed를 여러 번 호출할 수 있습니다. cmd를 다음과 같이 구분하세요. (모두 감사합니다...) 여러 cmd ;에 이것을 사용할 수 있는 방법이 있나요 ?awk -F

sed다중 파이프 사용


echo "'text';" | \
sed s"#';##"g  | \ 
sed s"#'##"g   

text

구분 기호 sed로 사용;


echo "'text';" | \
sed "            \
  s#';##g;       \
  s#'##g         \
"

text

편집하다:

따라서 awk.dll을 사용하여 여러 cmd에 참여할 수 있습니다 ;. 하지만 awk -F여러 cmd에서는 이 작업을 수행 할 수 없습니다.

문제는 여러 awk -F명령을 연결하는 것에 관한 것인데 아직 답변이 없습니다.

배경


# '/x/ gives the href of the actual videos
# awk -F '/x/' '{print$2}’ 
# because the /x/ is unique to the video urls
# after this the video links appear
# but I have to get rid of stuff 
# on the right of them so I do 
# awk —F 'title' '{print$1}' 
# this returns all the video links 
# but they have a double quotes 
# and a semi colon on the end.

curl -s                                 \
  https://site.com/plist/page={0..50} | \
grep '/x/'                            | \
awk -F '/x/' '{print$2}'              | \
awk -F 'title' '{print$1}'            | \
sed '                                   \
  s#";##g;                              \
  s#"##g                                \
'

이제 많은 비디오 링크가 있고 비디오 다운로드 링크를 얻기 위해 추가 처리를 수행한 다음 mapfile다운로드 링크를 배열로 가져와 parallel다운로드하는 데 사용합니다.

이 코드 예제에서는 실제로 수행되는 작업을 많이 단축했습니다.

편집하다:

그래서 이것은 할 수 없습니다. 이 사용자에게 깊은 감사를 드립니다.

이 사용자는 sed내 특정 사례의 경우 이것이 필요하지 않다고 말했지만 awk -F적어도 20개의 다른 사례가 있습니다. 하지만 이는 나에게 생각할 거리를 줬고, 내가 이 일을 하는 이유 awk -F는 sed 정규식을 전혀 몰라도 나에게 필요한 것을 제공하기 때문입니다.

아무튼 다들 고마워요, 할 수 있을까 싶었는데 못해서 만족해요.

감사해요

@StèphaneChazelas에게 그들의 의견이 내 문제를 해결했습니다.

답변1

고쳐 쓰다:문제는실질적인 변화이 답변을 게시한 후에도 원래 답변은 여전히 ​​정확하지만 문제를 해결하는 데 큰 도움이 되지 않습니다.실제OP님의 질문입니다.

curl양식의 출력을 처리하려는 것 같습니다.

Ignore this
http://some.url.involving/x/'video-link-1';title...
http://some.url.involving/x/'video-link-2';title...
Ignore that

잠깐만요, 어디로 가고 싶어요?

  1. 표시된 행만 처리됩니다 /x/.
  2. 중간 부분을 추출해 보세요.' ... '

가장 간단한 방법은 하나의 필드 구분 기호만 사용하는 것입니다 '.

curl -s https://site.com/plist/page={0..50} | awk -F"'" '/\/x\//{print $2}'

또한 /x/해당 패턴이 포함된 행만 고려됩니다. 따라서 위 예의 경우 출력은 다음과 같습니다.

video-link-1
video-link-2

분할을 위한 필드 구분 기호를 변경하여 이 작업을 수행하려는 경우, 물론 FS내부 변수를 중간에 변경할 수 있습니다.Stephen Chazeras의 답변. 그러나 이 경우에는 -F옵션 매개변수로 설정 하든지 프로그램 FS내부 할당을 통해 설정하든 상관없이 다중 문자 필드 구분 기호가 awk전체 정규식으로 처리된다는 사실을 사용하고 싶습니다 .

즉, "or" 유형 재정의를 필드 구분 기호로 사용하여 두 경우 모두를 처리할 수 있습니다(단, 추가 후처리가 필요하지 않도록 작은따옴표와 세미콜론도 포함해야 합니다).

curl -s https://site.com/plist/page={0..50} |
   awk -F'/x/\047|\047;title' '/\/x\//{print $2}'
  • 그러면 필드 구분 기호가 다음으로 설정됩니다.누구나 /x/' 또는 ';title.
  • 이 패턴이 포함된 행만 고려합니다 /x/. 이 줄에는 원하는 정보인 두 번째 필드가 인쇄됩니다( 및 제거됨 ') ;.
  • 작은 따옴표는 "작은 따옴표 안에 작은 따옴표" 문제를 피하기 위해 ASCII 코드로 표시됩니다. \047(나는 단지 귀하의 OS가 ASCII 기반 시스템이라고 가정하고 있습니다.EBCDIC).

자주 접하는 또 다른 방법"전체 줄을 흥미로운 부분으로만 교체"입니다.

curl -s https://site.com/plist/page={0..50} |
   awk '/\/x\//{print gensub(/.*\/x\/\047([^\047]+).*/,"\\1","1")}'

그러면 다시 /x/패턴이 발생한 줄만 고려하여 전체 줄을 패턴 뒤에 오는 작은따옴표 사이의 내용으로 바꾸고 수정된 줄을 인쇄하여 해당 부분만 추출합니다.

단일 sed호출로 동일한 효과를 얻을 수 있지만 ASCII 코드를 통해 작은따옴표를 표현하는 것은 여기서 작동하지 않으므로 조금 더 복잡합니다. GNU에 ERE 옵션이 sed있다고 가정하면:-E

curl -s https://site.com/plist/page={0..50} | sed -n -E 's|.*\/x\/'\''([^'\'']+).*|\1|p'

이는 기본적으로 출력을 억제하고 -n, 케이스와 같은 교체를 수행한 awk다음 (후행 p) 을 인쇄합니다.교체시에만, 이는 패턴이 발견되었음을 의미합니다./x/'video-link';title


원래 답변은 다음과 같습니다

프레임워크 과제:그게 필요 할까?

에서는 awk동일한 프로그램의 수정 명령을 필요한 만큼 반복할 수 있습니다.

echo "'text';" | awk '{gsub(/\047;/,""); gsub(/\047/,"")} 1'

또는

echo "'text';" | awk '{gsub(/\047;/,"")} {gsub(/\047/,"")} 1'

( \047작은따옴표 프로그램에서 작은따옴표를 표현하는 데 사용됩니다.)

다음과 같이 읽기 쉬운 방식으로 작성할 수도 있습니다.

echo "'text';" |
  awk '{gsub(/\047;/,"")};
       {gsub(/\047/,"")}; 1'

또는 전용 프로그램으로:

echo "'text';" | awk -f multi-substitute.awk

multi-substitute.awk처럼 보인다

#!/usr/bin/awk -f
{gsub(/\047;/,"")}
{gsub(/\047/,"")}
1

답변2

문제는 무엇입니까:

echo "'text';" | sed "
  s/';//g
  s/'//g
"

또는:

awk -v q="'" '
  {
    gsub(q ";", "")
    gsub(q, "")
    print
  }'

또는:

awk -v q="'" '
  {
    gsub(q ";", "")
  }
  {
    gsub(q, "")
  }
  {
    print
  }'

이 질문에 대해서요?

-e초는 필요하지 않습니다. (t)csh가 PITA라는 점을 제외하면 대부분의 쉘은 여러 줄 인수를 입력해야 하는 요구 사항에 완벽하게 적합합니다.

-e argin은 sed실제로 코드에 arg개행 문자를 추가 하도록 지정 sed되었으므로

sed -e foo -e bar

~와 함께라는 뜻이다

sed 'foo
bar'

다음 작업을 수행하는 것을 막을 수 있는 것은 없습니다.

NL='
' # or NL=$'\n' with most modern shells.

sed_cmd1='s/foo/bar' awk_cmd1='gsub(/foo/, "bar")'
sed_cmd2='s/bar/baz' awk_cmd2='gsub(/bar/, "baz")'

sed "$sed_cmd1$NL$sed_cmd2"
# or
awk "{$awk_cmd1$NL$awk_cmd2${NL}print}"

또는:

awk "$(printf '%s\n' '{gsub("foo", "bar"}' '{gsub("bar", "baz")}')"

구문적으로 awk개행 문자를 로 바꾸어 명령을 구분할 수 있습니다 ;. 또한 가능 sed하지만 제한된 수의 명령 이후에만 가능합니다 ( w, r, :, a, c, i, , 또는 명령 이후는 아님 b, 예 를 들어 플래그가 사용되는 경우 적어도 이식 가능함).t}#sw

참조에 대한 걱정을 피하려면 다음을 수행할 수도 있습니다.

awk "$(<<'EOF' cat
  {
    gsub("';", "") # ' " \ not a problem
    gsub("'", "")
    print
  }
EOF
)"

또는 대부분의 시스템에서:

awk -f /dev/fd/3 3<<'EOF'
  {
    gsub("';", "") # ' " \ not a problem
    gsub("'", "")
    print
  }
EOF

EOF( 이 문서의 셸이 확장을 수행하지 않도록 하려면 첫 번째 항목 주위에 따옴표를 참고하세요 .)


여러 s를 편집 하는 경우 -F(와 혼동하지 마세요 -f):

-F x필드 구분 기호를 로 설정하거나 를 x사용하거나 -v FS=x추가하는 것입니다 BEGIN { FS = "x" }.

예를 들어 이렇게 하면 세 번째 구분 필드의 두 번째 공백 구분 필드의 첫 번째 공백 구분 필드를 -F ' ' -F '|' -F ','가져오는 데 도움이 되지 않습니다 . 으로 만 설정됩니다 .,|foo a|b|x,y,z|c barFS,

이를 위해서는 다음이 필요합니다.

awk '
  {
    split($0, a, " ")
    split(a[2], b, "|")
    split(b[3], c, ",")
    print c[1]
  }'

또는 다음을 사용하십시오 FS.

awk '
  {
    FS = " "; $0 = $2
    FS = "|"; $0 = $3
    FS = ","; print $1
  }'

FS$0여기서는 액세스할 때(x >= 1) 분할(초기 현재 레코드의 내용)하기 위해 사용됩니다 .$x

IOW, 줄일 수 있습니다

awk '{print "something out of "$0}' |
  awk '{print "something out of "$0" as modified by the first}'

다음을 수행해야 합니다.

awk '
  {
    $0 = "something out of "$0
    print "something out of "$0" as modified by the first
  }'

두 개의 seds를 s/x/y/각각 하나씩 수행하거나 두 개의 awks 에 해당하는 작업을 수행하는 것으로 쉽게 줄일 수 있지만 반드시 두 코드 중 {gsub("x", "y"); print}하나에 동일한 방법을 적용할 필요는 없습니다 . 단지 작동 방식과 하나의 레코드를 처리한다는 점만 이해하면 됩니다. 한 번에 텍스트 스트림이 들어올 때.sedawk

답변3

sed그리고-e

echo "'text';" | sed s"#';##"g  | sed s"#'##"g  
text

echo "'text';" | sed -e s"#';##"g -e s"#'##"g  
text

일반적으로 여러 명령을 사용할 필요가 없으며 -e두 번 사용할 필요도 없습니다(세미콜론만 사용). awk 또는 sed의 단일 인스턴스가 두 작업을 모두 처리하도록 허용하는 것이 더 빠를 수도 있습니다.

$ echo "'text';" | sed "s/';//g; s/'//g"
text

캡처를 사용하여 이 작업을 수행했을 수도 있습니다.

$ echo "'text';" | sed -r "s/'([^']*)';/\1/g"
text

물론, 나는 당신의 간단한 예가 이러한 방식으로 쉽게 결합될 수 없는 한 쌍의 프로그램에 대한 자리 표시자라는 것을 의심하지 않습니다. 하지만 초보자들이 잘못된 인상을 받는 것을 원하지 않습니다. 간단한 작업은 이런 방식으로 결합하는 것이 가장 좋습니다.


awk그리고-F

curl -s                                 \
  https://site.com/plist/page={0..50} | \
grep '/x/'                            | \
awk -F '/x/' '{print$2}'              | \
awk -F 'title' '{print$1}'            | \
sed '                                   \
  s#";##g;                              \
  s#"##g                                \
'

AWK를 사용하면 다른 사람들이 지적했듯이 다양한 표현식에 대해 서로 다른 필드 구분 기호를 설정하는 것보다 완전히 다른 접근 방식을 사용하는 것이 좋습니다. 정규 표현식이 모든 데이터의 구조를 적절하게 표현할 수 있다면 이는 구분 기호가 혼합된 문자열에서 항목을 추출하는 가장 좋은 방법일 수 있습니다. 정규 표현식은 과도하게 사용되는 경우가 많지만 무시해서는 안 됩니다.

이 데이터가 주어지면:

$ cat /tmp/titles.txt
preamble
p/q/r/s/title"Not This";Brick
something
a/x/b/c/title"The Rime of the Ancient Mariner";Coleridge
otherthing
f/g/x/h/title"Jackass";Knoxville
remainder

Perl에서 위의 모든 작업을 수행하려고 할 수도 있습니다.

$ curl -s file:///tmp/titles.txt | \
> perl -n -e 'print "$1\n" if m{/x/.*title"([^"]*)";}'
The Rime of the Ancient Mariner
Jackass

이는 Curl과 단일 AWK 프로그램을 사용하여 쉽게 수행할 수 있습니다. 나는 AWK 전문가는 아니지만 아마도 다음부터 시작하여 개선할 것입니다.

$ curl -s file:///tmp/titles.txt | \
> awk '/\/x\// {gsub(".*title\"",""); gsub("\";.*",""); print}'
The Rime of the Ancient Mariner
Jackass

(Gnu Sed 4.2.2, Perl 5.18.2. Gnu AWK 4.0.1)

답변4

당신이 좋은 GNU를 가지고 있다면 awk그렇습니다

% printf abc'\n' | gawk -e '{print}' -e '{print}'
abc
abc

그렇지 않으면 아마도 그렇지 않을 것입니다.

% printf abc'\n' | awk -e '{print}' -e '{print}'
awk: unknown option -e ignored

awk: can't open file -e
 source line number 1

ZSH와 같은 멋진 쉘을 사용하면 다음과 같은 끔찍한 일을 할 수 있지만 이 시점에서는 아마도 스크립트를 올바른 파일에 넣고 실행해야 할 것입니다.

% print -l abc | awk -f <(print "{print}") -f <(print "{print}")
abc
abc

관련 정보