"[]] ওয়াইল্ডকার্ড ব্যবহার করে PATINDEX এর সাথে একটি] (বর্গাকার বন্ধনী বন্ধ করে) মিলছে


9

আমি টি-SQL এর যে একটি কাস্টম JSON বিশ্লেষক লিখছি

আমার পার্সারের উদ্দেশ্যে, আমি PATINDEXটোকেনের তালিকা থেকে একটি টোকেনের অবস্থান গণনা করে এমন ফাংশনটি ব্যবহার করছি । আমার ক্ষেত্রে টোকেনগুলি সমস্ত একক অক্ষর এবং সেগুলিতে এগুলি অন্তর্ভুক্ত করে:

{} []:,

সাধারণত, যখন আমাকে কয়েকটি প্রদত্ত চরিত্রের (প্রথম) অবস্থানের সন্ধান করতে হয়, তখন আমি PATINDEXএই ফাংশনটি ব্যবহার করি :

PATINDEX('%[abc]%', SourceString)

ফাংশন তারপর আমার প্রথম স্থান দিতে হবে aবা bবা cমধ্যে - যেটি আগে পাওয়া যাবে এরকম - SourceString

এখন আমার ক্ষেত্রে সমস্যাটি ]চরিত্রটির সাথে সংযুক্ত বলে মনে হচ্ছে । চরিত্রের তালিকায় এটি নির্দিষ্ট করার সাথে সাথে যেমন:

PATINDEX('%[[]{}:,]%', SourceString)

স্পষ্টতই আমার মিলিত প্যাটার্নটি ভেঙে যায়, কারণ ফাংশনটি কোনও মিল খুঁজে পায় না। দেখে মনে হচ্ছে প্রথমটি থেকে বাঁচার জন্য আমার একটি উপায় দরকার ]যাতে PATINDEXএটি একটি বিশেষ প্রতীক না হয়ে দেখার জন্য অন্যতম চরিত্র হিসাবে বিবেচনা করে।

আমি এই প্রশ্নটি একই ধরণের সমস্যার বিষয়ে জিজ্ঞাসা করে পেয়েছি:

তবে, সেক্ষেত্রে ]কেবল বন্ধনীগুলিতে নির্দিষ্ট করার প্রয়োজন হয় না, কারণ এটি কেবল একটি অক্ষর এবং এটি চারপাশে বন্ধনী ছাড়াই নির্দিষ্ট করা যেতে পারে। বিকল্প সমাধান, যা পলায়ন ব্যবহার করে, কেবল তার জন্য কাজ করে LIKEএবং না PATINDEX, কারণ এটি একটি ESCAPEউপবৃত্ত ব্যবহার করে, প্রাক্তন দ্বারা সমর্থিত এবং পরবর্তীকালের দ্বারা নয়।

সুতরাং, আমার প্রশ্ন হল, কোন উপায় আছে একটি সন্ধান করা হয় ]সঙ্গে PATINDEXব্যবহার [ ]ওয়াইল্ডকার্ড? বা অন্যান্য ট্রান্সঅ্যাক্ট-এসকিউএল সরঞ্জাম ব্যবহার করে সেই কার্যকারিতা অনুকরণ করার কোনও উপায় আছে?

অতিরিক্ত তথ্য

এখানে একটি ক্যোয়ারী যেখানে আমি ব্যবহার করতে হবে একটি উদাহরণ PATINDEXদিয়ে […]উপরের মতো প্যাটার্ন। এখানে প্যাটার্নটি কাজ করে ( কিছুটা হলেও ) কারণ এতে ]চরিত্রটি অন্তর্ভুক্ত নয়। ]পাশাপাশি কাজ করাও আমার দরকার :

WITH
  data AS (SELECT CAST('{"f1":["v1","v2"],"f2":"v3"}' AS varchar(max)) AS ResponseJSON),
  parser AS
  (
    SELECT
      Level         = 1,
      OpenClose     = 1,
      P             = p.P,
      S             = SUBSTRING(d.ResponseJSON, 1, NULLIF(p.P, 0) - 1),
      C             = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0), 1),
      ResponseJSON  = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0) + 1, 999999)
    FROM
      data AS d
      CROSS APPLY (SELECT PATINDEX('%[[{]%', d.ResponseJSON)) AS p (P)
    UNION ALL
    SELECT
      Level         = ISNULL(d.OpenClose - 1, 0) + d.Level + ISNULL(oc.OpenClose, 0),
      OpenClose     = oc.OpenClose,
      P             = d.P + p.P,
      S             = SUBSTRING(d.ResponseJSON, 1, NULLIF(p.P, 0) - 1),
      C             = c.C,
      ResponseJSON  = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0) + 1, 999999)
    FROM
      parser AS d
      CROSS APPLY (SELECT PATINDEX('%[[{}:,]%' COLLATE Latin1_General_BIN2, d.ResponseJSON)) AS p (P)
      CROSS APPLY (SELECT SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0), 1)) AS c (C)
      CROSS APPLY (SELECT CASE WHEN c.C IN ('[', '{') THEN 1 WHEN c.C IN (']', '}') THEN 0 END) AS oc (OpenClose)
    WHERE 1=1
      AND p.P <> 0
  )
SELECT
  *
FROM
  parser
OPTION
  (MAXRECURSION 0)
;

আমি যে আউটপুট পাই তা হ'ল:

Level  OpenClose  P   S      C   ResponseJSON
-----  ---------  --  -----  --  ---------------------------
1      1          1          {   "f1":["v1","v2"],"f2":"v3"}
1      null       6   "f1"   :   ["v1","v2"],"f2":"v3"}
2      1          7          [   "v1","v2"],"f2":"v3"}
2      null       12  "v1"   ,   "v2"],"f2":"v3"}
2      null       18  "v2"]  ,   "f2":"v3"}
2      null       23  "f2"   :   "v3"}
2      0          28  "v3"   }   

আপনি দেখতে পাচ্ছেন যে সারিগুলির মধ্যে একটিতে ]অংশটি অন্তর্ভুক্ত রয়েছে SLevelকলাম, পাখির বন্ধনী অর্থ এবং ধনুর্বন্ধনী পাখির মাত্রা নির্দেশ করে। যেহেতু আপনি দেখতে পারেন, একবার স্তর 2 হয়ে, এটি 1. ফিরে কখনো কি তা পারতে যদি আমি বানাতে পারে PATINDEXচিনতে ]একটি টোকেন হিসাবে।

উপরের উদাহরণের জন্য প্রত্যাশিত ফলাফল:

Level  OpenClose  P   S     C   ResponseJSON
-----  ---------  --  ----  --  ---------------------------
1      1          1         {   "f1":["v1","v2"],"f2":"v3"}
1      NULL       6   "f1"  :   ["v1","v2"],"f2":"v3"}
2      1          7         [   "v1","v2"],"f2":"v3"}
2      NULL       12  "v1"  ,   "v2"],"f2":"v3"}
2      0          17  "v2"  ]   ,"f2":"v3"}
1      NULL       18        ,   "f2":"v3"}
1      NULL       23  "f2"  :   "v3"}
1      0          28  "v3"  }

আপনি এই ক্যোয়ারির সাথে ডিবি <> ফিডল খেলতে পারেন ।


আমরা এসকিউএল সার্ভার 2014 ব্যবহার করছি এবং শীঘ্রই এমন কোনও সংস্করণে আপগ্রেড হওয়ার সম্ভাবনা নেই যা জেএসএন স্থানীয়ভাবে পার্সিং সমর্থন করে। আমি কাজটি করার জন্য একটি আবেদন লিখতে পারি তবে পার্সিংয়ের ফলাফলগুলিকে আরও প্রক্রিয়া করা প্রয়োজন, যা অ্যাপ্লিকেশনটিতে কেবল বিশ্লেষণের চেয়ে আরও বেশি কাজ বোঝায় - এমন ধরণের কাজ যা আরও সহজ হবে এবং সম্ভবত আরও দক্ষতার সাথে সম্পন্ন হয়েছে একটি টি-এসকিউএল স্ক্রিপ্ট, কেবল যদি আমি এটি সরাসরি ফলাফলগুলিতে প্রয়োগ করতে পারি।

এই সমস্যাটির সমাধান হিসাবে আমি এসকিউএলসিআরআর ব্যবহার করতে পারি এমনটা খুব কমই। তবে, কেউ যদি এসকিউএলসিএলআর সমাধান পোস্ট করার সিদ্ধান্ত নেন তবে আমার আপত্তি নেই, যেহেতু এটি অন্যদের জন্য কার্যকর হতে পারে।


জেসন দেখতে দেখতে কেমন ["foo]bar”]?
সালমান এ

@ সালমানা: এ জাতীয় পরিস্থিতি নিরাপদে উপেক্ষা করা যেতে পারে।
অ্যান্ড্রি এম

উত্তর:


6

আমার নিজের সমাধানটি, যা অনেকটা কার্যকরী হয়, একটি চরিত্রের সীমা নির্দিষ্ট করতে ]এবং [ ]ওয়াইল্ডকার্ডের অন্যান্য চরিত্রের সাথে সেই ব্যাপ্তিটি ব্যবহার করে in আমি ASCII টেবিলের উপর ভিত্তি করে একটি ব্যাপ্তি ব্যবহার করেছি। সেই টেবিল অনুসারে, ]চরিত্রটি নিম্নলিখিত পাড়ার মধ্যে অবস্থিত:

হেক্স ডিস ডিস
--- --- ----
...
5 এ 90 জেড
5 বি 91 [
5C 92
5 ডি 93]
5E 94
5F 95 _
...

আমার পরিসীমা, তাই আকারে গ্রহণ [-^, IE চার অক্ষর অন্তর্ভূক্ত করেছেন: [, \, ], ^। আমি আরও উল্লেখ করেছি যে প্যাটার্নটি ASCII সীমার সাথে সামঞ্জস্য করার জন্য বাইনারি কোলেশন ব্যবহার করে col ফলস্বরূপ PATINDEXপ্রকাশটি এই মত দেখতে শেষ হয়েছিল:

PATINDEX('%[[-^{}:,]%' COLLATE Latin1_General_BIN2, MyJSONString)

এই পদ্ধতির সাথে সুস্পষ্ট সমস্যাটি হ'ল প্যাটার্নের শুরুতে পরিসীমাটিতে দুটি অযাচিত অক্ষর \এবং ^। সমাধানটি কেবলমাত্র আমার জন্য কাজ করেছিল কারণ অতিরিক্ত অক্ষরগুলি পার্স করার জন্য নির্দিষ্ট জেএসওএন স্ট্রিংগুলিতে কখনও ঘটতে পারে না। স্বাভাবিকভাবেই, এটি সাধারণভাবে সত্য হতে পারে না, তাই আমি এখনও অন্যান্য পদ্ধতিতে আগ্রহী, আশা করি আমার চেয়ে সর্বজনীন।


4

আমার যখন স্ট্রিং বিভাজন অনেকটা করতে হয়েছিল তখন পিছন থেকে আমার এটি সম্ভবত ভয়াবহ গ্রহণ।

আপনার যদি অক্ষরের একটি পরিচিত সেট থাকে তবে সেগুলির একটি টেবিল তৈরি করুন।

CREATE TABLE dbo.characters ( character CHAR(1) NOT NULL PRIMARY KEY CLUSTERED );

INSERT dbo.characters ( character )
SELECT *
FROM (
        SELECT '[' UNION ALL
        SELECT ']' UNION ALL
        SELECT '{' UNION ALL
        SELECT '}' UNION ALL
        SELECT ',' 
) AS x (v)

তারপর যে ঐন্দ্রজালিক ব্যবহার CROSS APPLYসহ CHARINDEX:

SELECT TOP 1000 p.Id, p.Body, ca.*
FROM dbo.Posts AS p
CROSS APPLY (
    SELECT TOP 1 CHARINDEX(c.character, p.Body) AS first_things_first
    FROM dbo.characters AS c
    ORDER BY CHARINDEX(c.character, p.Body) ASC
) AS ca
WHERE ca.first_things_first > 0

আপনার কী করা দরকার সে সম্পর্কে আমি যদি কিছু স্পষ্টরূপে অনুপস্থিত থাকি তবে লেমে জানুন।


4

আমি অতীতে অত্যাচারী চরিত্রটি অনুসন্ধানের আগে প্রতিস্থাপন এবং পরে এটিকে পুনরায় স্থাপন করার জন্য পন্থাগুলি দেখেছি।

এই ক্ষেত্রে আমরা যেমন কিছু করতে পারি:

DECLARE @test NVARCHAR(MAX);
DECLARE @replacementcharacter CHAR(1) = CHAR(174);

SET @test = 'Test[]@String'

SELECT PATINDEX('%[[' + @replacementcharacter + '@]%', REPLACE(@test,']',@Replacementcharacter))

এই কোডটি সঠিকভাবে 5 প্রদান করে I'm আমি ¬ চরিত্রটি ব্যবহার করার সম্ভাবনা হ'ল - যদি কোনও এসসিআইআই অক্ষর না থাকে তবে আপনি ব্যবহার করবেন না, এই সমাধানটি কাজ করবে না।

অদ্ভুতভাবে যথেষ্ট হলেও, আপনার প্রশ্নের সরাসরি উত্তর হ'ল না - আমি ']' এর জন্য অনুসন্ধানের জন্য PATINDEX পেতে পারি না, তবে আপনি যদি এটি প্রতিস্থাপন করেন তবে আপনার প্রয়োজন হবে না।

একই উদাহরণ কিন্তু পরিবর্তনশীল ব্যবহার ছাড়াই:

DECLARE @test NVARCHAR(MAX);

SET @test = 'Test[]@String'

SELECT PATINDEX('%[[' + CHAR(174) + '@]%', REPLACE(@test,']',CHAR(174)))

আপনার কোডে উপরের সমাধানটি ব্যবহার করা আপনার প্রয়োজনীয় ফলাফল দেয়:

WITH
  data AS (SELECT CAST('{"f1":["v1","v2"],"f2":"v3"}' AS varchar(max)) AS ResponseJSON),
  parser AS
  (
    SELECT
      Level         = 1,
      OpenClose     = 1,
      P             = p.P,
      S             = SUBSTRING(d.ResponseJSON, 1, NULLIF(p.P, 0) - 1),
      C             = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0), 1),
      ResponseJSON  = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0) + 1, 999999)
    FROM
      data AS d
      CROSS APPLY (SELECT PATINDEX('%[[{'+ CHAR(174) + ']%', REPLACE(d.ResponseJSON,']',CHAR(174)))) AS p (P)
    UNION ALL
    SELECT
      Level         = ISNULL(d.OpenClose - 1, 0) + d.Level + ISNULL(oc.OpenClose, 0),
      OpenClose     = oc.OpenClose,
      P             = d.P + p.P,
      S             = SUBSTRING(d.ResponseJSON, 1, NULLIF(p.P, 0) - 1),
      C             = c.C,
      ResponseJSON  = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0) + 1, 999999)
    FROM
      parser AS d
      CROSS APPLY (SELECT PATINDEX('%[[{}:,'+ CHAR(174) + ']%' COLLATE Latin1_General_BIN2, REPLACE(d.ResponseJSON,']',CHAR(174)))) AS p (P)
      CROSS APPLY (SELECT SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0), 1)) AS c (C)
      CROSS APPLY (SELECT CASE WHEN c.C IN ('[', '{') THEN 1 WHEN c.C IN (']', '}') THEN 0 END) AS oc (OpenClose)
    WHERE 1=1
      AND p.P <> 0
  )
SELECT
  *
FROM
  parser
OPTION
  (MAXRECURSION 0)
;

4

যেহেতু ]কেবলমাত্র বিশেষ [...], আপনি এর বাইরে PATINDEXচলে গিয়ে দুবার ব্যবহার করতে পারেন । উভয় মূল্যায়ন এবং । যদি একটি ফলাফল শূন্য হয় তবে অন্যটি নিন। অন্যথায়, দুটি মান কম গ্রহণ করুন।][...]PATINDEX('%[[{}:,]%', SourceString)PATINDEX('%]%', SourceString)

আপনার উদাহরণে:

WITH
  data AS (SELECT CAST('{"f1":["v1","v2"],"f2":"v3"}' AS varchar(max)) AS ResponseJSON),
  parser AS
  (
    SELECT
      Level         = 1,
      OpenClose     = 1,
      P             = p.P,
      S             = SUBSTRING(d.ResponseJSON, 1, NULLIF(p.P, 0) - 1),
      C             = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0), 1),
      ResponseJSON  = SUBSTRING(d.ResponseJSON, NULLIF(p.P, 0) + 1, 999999)
    FROM
      data AS d
      CROSS APPLY (SELECT PATINDEX('%[[{]%', d.ResponseJSON)) AS p (P)
    UNION ALL
    SELECT
      Level         = ISNULL(d.OpenClose - 1, 0) + d.Level + ISNULL(oc.OpenClose, 0),
      OpenClose     = oc.OpenClose,
      P             = d.P + ISNULL(p.P, 0),
      S             = SUBSTRING(d.ResponseJSON, 1, p.P - 1),
      C             = c.C,
      ResponseJSON  = SUBSTRING(d.ResponseJSON, p.P + 1, 999999)
    FROM
      parser AS d
      CROSS APPLY (VALUES (NULLIF(PATINDEX('%[[{}:,]%', d.ResponseJSON), 0), NULLIF(PATINDEX('%]%', d.ResponseJSON), 0))) AS p_ (a, b)
      CROSS APPLY (VALUES (CASE WHEN p_.a < p_.b OR p_.b IS NULL THEN p_.a ELSE p_.b END)) AS p (P)
      CROSS APPLY (SELECT SUBSTRING(d.ResponseJSON, p.P, 1)) AS c (C)
      CROSS APPLY (SELECT CASE WHEN c.C IN ('[', '{') THEN 1 WHEN c.C IN (']', '}') THEN 0 END) AS oc (OpenClose)
    WHERE 1=1
      AND p.P <> 0
  )
SELECT
  *
FROM
  parser
OPTION
  (MAXRECURSION 0)
;

https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=66fba2218d8d7d310d5a682be143f6eb


-4

একটি বাম জন্য '[':

PATINDEX('%[[]%',expression)

একটি অধিকারের জন্য ']':

PATINDEX('%]%',expression)

1
এটি একটি উদ্বোধনী বর্গক্ষেত্র বন্ধনী বা একটি বন্ধ হওয়া উভয়কে কীভাবে অনুসন্ধান করবেন তা নির্দিষ্ট করে; ক্লোজিং স্কোয়ার ব্র্যাকেট সহ ওপি বেশ কয়েকটি অক্ষরের একটি (বর্গাকার বন্ধনীতে প্রশ্নে অক্ষরগুলি আবদ্ধ করে চিহ্নিত) অনুসন্ধান করছে।
আরডিফোজ 17
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.